多级异步代码中的 Dart 错误

Dart Errors in multi-level asynchronous code

考虑以下代码

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() 立即 returning,然后稍后,在另一个上下文中,doSomethingElse() 抛出错误,立即停止所有执行。我知道这个问题的答案可能是 "Well, don't do that then." 但我正在考虑我可能无法控制我正在调用的方法的情况(比如它们是否是库的一部分)。

这种情况会引出几个相关的问题:

注意:我在这里使用 async/await 语法,但这个问题应该与更严格的基于 Future 的构造同样相关(你 return 在 doSomething() 中的新 Future而不是 .then()doSomethingElse()

中删除那个

喜欢 you can use Zones 以捕获异步代码中的意外错误。

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

您想要的是为您的代码引入不同的错误处理程序,通过 运行 通过 runZoned 错误处理程序:

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