请考虑以下代码
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 掉