我不明白为什么下面代码中addItem
方法抛出的错误没有在try-catch块中捕获
void main() async {
var executor = Executor();
var stream = Stream.fromIterable([0, 1, 2, 3, 4, 5, 6, 7]);
try {
await for (var _ in stream) {
executor.submit(() => demoMethod());
}
await executor.execute();
} catch (e) {
print(e);
}
}
Future<void> demoMethod() async {
var list = [1, 2, 3, 1, 4, 5];
var executor = Executor();
var test = Test();
for (var element in list) {
executor.submit(() => test.addItem(element));
}
await executor.execute();
test.list.forEach(print);
}
class Test {
var list = <int>[];
Future<void> addItem(int i) async {
if (list.contains(i)) {
throw Exception('Item exists');
}
list.add(i);
}
}
class Executor {
final List<Future<void>> _futures = [];
bool _disposed = false;
void submit(Future<void> Function() computation) {
if (!_disposed) {
_futures.add(computation());
} else {
throw Exception('Executor is already disposed');
}
}
Future<void> execute() async {
await Future.wait(_futures, eagerError: true);
_disposed = true;
}
}
但以下代码能够正确捕获错误
void main() async {
var executor = Executor();
try {
for (var i = 0; i < 10; i++) {
executor.submit(() => demoMethod());
}
await executor.execute();
} catch (e) {
print(e);
}
}
我猜这与流处理有关。
1条答案
按热度按时间yeotifhr1#
是小溪。
在其他例子中,我们同步运行循环a,调用
Executor.submit
进行所有计算,然后立即调用executor.execute()
,在调用返回future的函数和Future.wait
开始等待future之间没有异步间隙。在流代码中,每个流事件通过调用
Executor.submit
启动一个异步计算,这将创建一个future,将其存储在一个列表中,然后返回等待流。如果future在流结束和
Future.wait
被调用之前完成,并出现错误,那么future还没有附加错误处理程序,错误被认为是未处理的,并报告给当前Zone
的未捕获错误处理程序。这里是根区域,这意味着它是一个全局未捕获错误,可能会导致整个程序崩溃。你需要确保将来不会认为它的错误是未处理的,最简单的方法是将
submit
修改为:..ignore()
告诉未来,没有错误处理程序是可以的。你知道,因为代码稍后会返回并调用executor.execute
,所以任何错误仍然会被报告,所以稍微推迟一点应该是安全的。这就是Future.ignore
的用途。(Also我将
Exception
更改为StateError
,因为您应该使用StateError
来报告使用已被处置或停用的对象的人员。)