Dart:让流中抛出的异常传播并在调用者中捕获它
Posted
技术标签:
【中文标题】Dart:让流中抛出的异常传播并在调用者中捕获它【英文标题】:Dart: Let an exception thrown inside a stream propagate and catch it in the caller 【发布时间】:2021-07-15 11:19:01 【问题描述】:我希望在流内引发异常,以便由调用者在外部捕获和处理。
如果我尝试使用标准的 try-catch 块,如下所示,它确实有效:我得到 Uncaught Error: Exception。
通过在 DartPad 中运行下面的 sn-p 代码
void main() async
await for (var i in mainStream())
print(i);
Stream<int> subStreamA() async*
for (var i in List.generate(10, (i) => i))
if (i == 2)
throw Exception();
yield i;
Stream<int> subStreamB() async*
for (var i in List.generate(10, (i) => i + 10))
yield i;
Stream<int> mainStream() async*
try
yield* subStreamA();
yield* subStreamB();
catch (e)
print('CAUGHT! :)');
yield -1;
结果是:
0
1
Uncaught Error: Exception
我希望捕获异常,导致:
0
1
CAUGHT! :)
-1
我想到了一些“解决方案”,但它们有点可怕:(比如......
Stream<int> mainStream() async*
try
Exception? err;
yield* subStreamA().handleError((e)
err = e;
);
if (err != null) throw err!;
yield* subStreamB().handleError((e)
err = e;
);
if (err != null) throw err!;
catch (e)
print('CAUGHT! :)');
yield -1;
是否有一个干净的解决方案利用正常的 try-catch 而不使用肮脏的技巧?
【问题讨论】:
【参考方案1】:yield*
对 async*
标记方法的行为是 Dart 语言设计的一部分,其中描述了这一点:
监听
o
流,创建订阅s
,并为每个事件x
,或错误e
与堆栈跟踪t
,s
:...
否则,x
或e
和t
将添加到与m
关联的流中 按照它们在o
中出现的顺序。
https://dart.dev/guides/language/specifications/DartLangSpec-v2.10.pdf
因此,简单来说,这意味着当我们使用 yield*
时,我们正在转发来自 Stream
的事件和错误(使用堆栈跟踪)。
如果要捕获异常,我认为最简单的解决方案是将yield*
的使用重写为await for
循环,如下所示:
Stream<int> mainStream() async*
try
await for (final event in subStreamA())
yield event;
await for (final event in subStreamB())
yield event;
catch (e)
print('CAUGHT! :)');
yield -1;
通过此更改,我得到以下输出:
0
1
CAUGHT! :)
-1
【讨论】:
谢谢!这比我想到的所有解决方案都要干净 @gianmarcocalbi 更新了答案。该行为是 Dart 语言规范的一部分。 @gianmarcocalbi 如果您没有任何其他问题并且您觉得我的回答令人满意,请接受该回答。 :)以上是关于Dart:让流中抛出的异常传播并在调用者中捕获它的主要内容,如果未能解决你的问题,请参考以下文章