为什么Dart中的runZonedGuarded会阻止后续代码执行?
Dart runZonedGuarded 异步执行异常问题原理说明
问题复现代码
void main() async { await runZonedGuarded( () async { print("a"); throw "error"; }, (e, s) { print("b"); }, ); print("c"); }
现象
- 代码直接运行输出仅为:
a b
print("c")不会执行
2. 去掉throw "error"语句后输出为:
a c
底层原理说明
核心原因和runZonedGuarded的返回值规则、Dart异步异常的传播逻辑有关:
runZonedGuarded的返回值是一个Future,它的完成状态和你传入的第一个参数(zone根执行回调)的返回Future状态完全绑定。- 当zone根回调内部抛出未被回调内部捕获的异常时,异常会先触发你传入的
onError回调执行print("b"),但onError仅作为异常的监听回调,不会消费掉这个异常,runZonedGuarded返回的Future仍然会以异常状态完成。 - 代码中使用
await等待runZonedGuarded的返回值,当这个Future以异常状态完成时,异常会直接向上抛到main函数的上下文,而main函数没有对这段异步逻辑做异常捕获,因此main函数会直接终止执行,后续的print("c")自然不会被调用。 - 去掉
throw语句后,zone根回调正常执行完成,runZonedGuarded返回的Future以正常状态结束,await等待结束后就会继续执行后续的print("c")。
验证方案
如果希望异常场景下也能执行print("c"),只需要给await runZonedGuarded套一层try-catch捕获向上传播的异常即可:
void main() async { try { await runZonedGuarded( () async { print("a"); throw "error"; }, (e, s) { print("b"); }, ); } catch (e) { print("捕获外层传播异常:$e"); } print("c"); }
上述代码输出为:
a b 捕获外层传播异常:error c
内容的提问来源于stack exchange,提问作者Scorb
相关产品推荐
相关产品推荐

