我没有这种行为...

main(args) async {
  await runZoned(() {
    throw false;
  }, onError: (e) async {
    print("working in onError");
    await runZoned(() {
      throw false;
    }, onError: (e) async {
      print("error 1");
    });
    print("error 2");
  });
  print("finish");
}
main(args) async {
  await runZoned(() async {
    throw await Future.error(false);
  }, onError: (e) async {
    print("working in onError");
    await await runZoned(() async {
      throw await Future.error(false);
    }, onError: (e) async {
      print("error 1");
    });
    print("error 2");
  });
  print("finish");
}

那些在runZoned()上异步的控件会从根本上改变行为,应该这样做吗?
我需要那些异步方法并始终达到print("finish")。我该如何解决这个问题?

最佳答案

您正在触及期货和错误(处理)区域的尖锐边缘。

在一个错误区域中引发的错误不会传播到将来在另一个错误区域中创建的错误处理程序。
因此,如果您从不同的错误区域获得了 future ,并且它已经完成并出现了错误,那么您将无法获得错误,也就没有值(value)可取,因此 future 将看起来永远无法完成。

编码

main(args) async {
  await runZoned(() async {
    await Future.error(false);
  }, onError: (e) async {
    print("working in onError");
    await runZoned(() async {
      await Future.error(false);
    }, onError: (e) async {
      print("error 1");
    });
    print("error 2");
  });
  print("finish");
}

在新的错误区域中将参数运行到runZone。它们是返回期货的异步函数,因此await Future.error(false)将抛出并完成返回的期货,并在该特定错误区域中出错。

然后,当runZoned完成时,它将返回该将来,并在与调用不同的错误区域中创建错误。它是await ed(在根区域,这是一个不同的错误区域),因此await runZoned(() async { ... }, ...)永远不会完成。 await等待将来完成,将来拒绝将完成的错误提供给侦听器,因此没有任何反应。

实际上,您正在等待一个永远不会完成的 future ,这就是您的程序在此时停止的原因。

因此,这可以按预期方式工作-错误永远不会离开在其创建时所在的错误区域,但是会使外部区域没有任何结果。

第一个示例之所以有效,是因为您正在同步抛出而不返回将来。立即捕获同步引发,然后runZoned返回null。 (不过,当Dart获得非可空类型时,这将不得不更改)。

通常,使用runZoned处理程序返回可能包含来自onError的错误的期货可能不是一个好主意。我们不能阻止这种情况(返回Object很好,而Future是对象),但是应该将其记录下来。

关于asynchronous - Dart在异步修改的主体上的runZoned()行为,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58335158/

10-11 12:50