简体   繁体   English

如何在Dart(Flutter)的回调函数中捕获异常?

[英]How to catch exception in a callback function in Dart (Flutter)?

I'm using WebSocket variable in my MyWebSocket class. 我在MyWebSocket类中使用WebSocket变量。 For listen i give a callback function as parameter. 对于侦听,我提供一个回调函数作为参数。 If this callback function throws an exception in calling class MyChat , then i can not catch that exception anywhere. 如果此回调函数在调用类MyChat引发异常,则我无法在任何地方捕获该异常。

My simplified code is: 我的简化代码是:

class MyWebSocket {
  WebSocket _ws;
  ...
  // initialized in controller: _ws = WebSocket.connect(_some_url_);
  // everything works (connect, listen)
  ...
  void listen({void Function(dynamic) myOnListen}) {
    try {
      _ws.listen(myOnListen)
        .onError((e) => print("MyWebSocket in MyChat.onError: $e"));
    } catch (e) {
      print("Catched in MyWebSocket: $e");
    }
  }
}


class MyChat {
  MyWebSocket _chatWs = MyWebSocket();
  ...
  void initWS() {
    try {
      _chatWs.listen(myOnListen: processMsg);
    } catch (e) {
      print("Catched in MyChat: $e");
    }
  }

  void processMsg(dynamic msg) {
    if(_some_stuff_like_invalid_msg_or_not_logged_in_...)
      throw Exception("There is my Exception");
  }
}

I have built try-catch in every possible place to catch exceptions - no success, i got only unhandled exception: 我在每个可能的地方都建立了try-catch来捕获异常-没有成功,我只有未处理的异常:

E/flutter: [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: Exception: There is my Exception E / flutter:[错误:flutter / lib / ui / ui_dart_state.cc(148)]未处理的异常:异常:有我的异常

E/flutter: #0 MyChat.processMsg E / Flutter:#0 MyChat.processMsg

Beware that you cannot use the passed listener as a key for later removal. 请注意,您不能将传递的侦听器用作以后删除的键。 For that you can pass the new listener created in MyWebSocket class when listen() is called, then use this key to remove the listener. 为此,可以在调用listen()时传递在MyWebSocket类中创建的新侦听器,然后使用此键删除侦听器。

class MyWebSocket {
  WebSocket _ws;
  void listen({void Function(dynamic) myOnListen, void Function(Error) onError}) {
    try {
      _ws.listen((){
        try {
          myOnListen({"label": "DATA"});
        } catch (e) {
          if(onError is Function)
          onError(e)
        }
      })
        .onError(onError);
    } catch (e) {
      print("Catched in MyWebSocket: $e");
    }
  }
}


class MyChat {
  MyWebSocket _chatWs = MyWebSocket();
  void initWS() {
    try {
      _chatWs.listen(myOnListen: processMsg, onError: (Error error){
        print("ERROR: "+error.toString());
      });
    } catch (e) {
      print("Catched in MyChat: $e");
    }
  }

  void processMsg(dynamic msg) {
    if(_some_stuff_like_invalid_msg_or_not_logged_in_...)
      throw Exception("There is my Exception");
  }
}

You need to handle it inside your processMsg 您需要在您的过程中处理它
If you analyze carefully the execution of your code the _ws.listent register a listener for when you receive a message and that will happen in the FUTURE, but you don't get an error WHILE you are REGISTERING your listener that's why that doesn't work the way you expect. 如果您仔细分析代码的执行情况, _ws.listent将在您收到消息时注册一个侦听器,这将在将来发生,但不会出现错误,而您正在注册侦听器,这就是为什么不这样做以您期望的方式工作。
processMsg will do something in the future, it will throw an error and it's at the end of the pipeline. processMsg将来会做一些事情,会引发错误,并且会在管道的尽头。
You are simulating an exception and nothing is handling it, it happens in a different stack frame, in the future. 您正在模拟一个异常,但是什么也没有处理,将来它会在不同的堆栈帧中发生。
The void listen({void Function(dynamic) myOnListen}) function execution is long gone when you receive and you precessMsg . 当您收到并precessMsg时, void listen({void Function(dynamic) myOnListen})函数执行已久。
Alternatively you could do: 或者,您可以执行以下操作:

Function tryCatchHOF(Function cb) {
  decorated(dynamic param) {
    try {
      cb(param);
    } catch (e) {
      print("$e");
    }
  }

  ;
  return decorated;
}

void processMsg(dynamic msg) {
  if (true) throw Exception("There is my Exception");
}

var processMsgWithTryCatch = tryCatchHOF(processMsg);
  processMsgWithTryCatch('');

and then pass processMsgWithTryCatch down to your listener if you don't want to handle inside processMsg 如果不想在processMsg内部处理,则将processMsgWithTryCatch传递给您的侦听器

I hope that make sense 我希望这有道理

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM