考虑以下代码
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()
(例如它写入日志,那么我既不需要输出也不需要担心处理错误)。我可以做些什么来防止doSomethingElse()
中的错误暂停程序,而不是将每次调用它包装成try / catch块(这可能很容易被忽略)?doSomethingElse()
的作者,是否有一些我可以使用的模式允许我以等待Future完成的调用者自己处理异常而不等待的调用者的方式抛出异常对于Future而言,不必担心捕获异常?在这方面我最好的想法是返回一个特殊的对象,而不是抛出异常,但这会增加很多额外的瑕疵,使得该方法的使用更加困难。注意:我在这里使用async / await语法,但问题应该与更严格的基于Future的构造同等相关(在doSomething()
而不是.then()
中返回一个新的Future关闭来自doSomethingElse()
答案 0 :(得分:6)
未捕获的异步错误将被处理到当前区域的错误处理程序。 你所看到的是root-zone的错误处理程序,它将错误报告为未捕获,这也终止了隔离。
你想要的是为代码引入一个不同的错误处理程序,方法是通过runZoned
运行错误处理程序:
import "dart:async";
main() {
runZoned(() async {
try {
print("trying");
await doSomething();
print("success");
} catch (e) {
print("caught");
}
}, onError: (e, s) {
print("uncaught");
});
}
答案 1 :(得分:0)
与Greg pointed in its comment一样,您可以使用Zones来捕获异步代码中的意外错误。