请考虑以下代码

import 'dart:async';

Future main() async {
  try {
    print("trying");
    await doSomething();
    print("success");
  } catch (e) {
    print("caught");
  }
}

Future<int> doSomething() async {
  await doSomethingElse();
  return 5;
}

Future<int> doSomethingElse() async {
  throw new Exception();
}

当运行时,在doSomethingElse()中抛出的异常在main()中被捕获,并且一切都按预期工作.但是,假设编写doSomething()方法的人没有意识到doSomethingElse()是异步的,而是编写了以下代码(请注意缺少的await).

Future<int> doSomething() async {
  doSomethingElse();
  return 5;
}

现在根本没有捕捉到异常.相反,现在的输出如下所示:

trying
success
Unhandled exception:
Uncaught Error: Exception
Stack Trace:
#0      doSomethingElse.<doSomethingElse_async_body> (file:///C:/code/test.dart:19:7)
#1      Future.Future.<anonymous closure> (dart:async/future.dart:118)
<snip>

发生的情况是doSomething()立即返回,然后一段时间之后,在另一个上下文中,doSomethingElse()抛出错误,立即停止所有执行.我知道这个问题的答案可能是"好吧,那就别那么做了."但是我正在考虑我可能无法控制我要调用的方法的情况(例如,如果它们是库的一部分).

这种情况导致了几个相关问题:

  • 作为main()的作者,有没有什么方法可以确保我对doSomething()的呼叫不会以未处理的异常结束?或者,我是否依赖doSomething()的作者来确保所有可能的异常都得到处理或传播到"返回的future "?有没有一种方法可以附加某种全局错误处理程序,可以从放弃的期货中捕获错误?
  • 作为《doSomething()》的作者,如果我不想等待doSomethingElse()(比如说它写入日志(log),所以我既不需要输出,也不需要担心处理错误).除了将doSomethingElse()中的每个调用包装为try/catch块(这可能很麻烦,而且很容易被忽略),我还能做些什么来防止doSomethingElse()中的错误停止程序?
  • 作为《doSomethingElse()》的作者,我是否可以使用某种模式来抛出异常,让等待future 完成的调用方可以自己处理该异常,而不等待future 的调用方不必担心捕获异常?在这方面,我最好的 idea 是返回一个特殊的对象,而不是抛出一个异常,但这会增加很多额外的麻烦,使该方法更难使用.

注意:我在这里使用的是异步/等待语法,但是这个问题对于更严格的基于future 的构造也应该是同样相关的(在这种构造中,您在doSomething()中返回一个新的Future,而不是将doSomethingElse()中的一个从.then()中go 掉

推荐答案

未捕获的异步错误被处理到当前区域的错误处理程序. 您看到的是根区域的错误处理程序将错误报告为未捕获,这也会终止隔离.

您需要为代码引入不同的错误处理程序,方法是使用错误处理程序运行runZoned次:

import "dart:async";
main() {
  runZoned(() async {
    try {
      print("trying");
      await doSomething();
      print("success");
    } catch (e) {
      print("caught");
    }
  }, onError: (e, s) {
    print("uncaught");
  });
}

Dart相关问答推荐

Dart 中 ThemeData 类的 copyWith() 方法

在polymer和dart中将内容标签渲染为模板的一部分

执行 `dart2js` 时会生成哪些文件?为什么?

Dart / Flutter 错误:没有为类Logger定义toStringDeep

了解Dart private class

当文本在 Flutter 中溢出时如何使 Text 小部件像选取框一样

Flatter BLoC-如何将参数传递给事件?

如何实现从左侧滑动的侧边菜单?

dart和下划线

在 Dart 中编写单元测试的最佳方式是什么?

Dart 是否支持参数化单元测试?

Dart 中的抽象基类

如何在 Dart 中将 UTF-8 字符串转换为字节数组?

Dart 的服务器端框架

我应该如何在 Dart 中测试 Future?

使用 Futures 时 .then() 和 .whenCompleted() 方法之间的区别?

在 Dart 中打开类类型

如何停止 Dart 的 .forEach()?

什么是 ?? Dart 中的双问号?

Dart 如何获取枚举的value