Dart 调用'Completer.completeError'时引发异常`

Dart 调用'Completer.completeError'时引发异常`,dart,Dart,请比较以下两个示例: 例1: import 'dart:async'; Future<void> main() async { final c = Completer<void>(); print(1); c.completeError(Exception("hello")); print(2); await c.future; } 例2: import 'dart:async'; Future<void> mai

请比较以下两个示例:

例1:

import 'dart:async';

Future<void> main() async {
  final c = Completer<void>();
  print(1);
  c.completeError(Exception("hello"));
  print(2);
  await c.future;
}
例2:

import 'dart:async';

Future<void> main() async {
  final c = Completer<void>();
  print(1);
  await (() async => c.completeError(Exception("hello")))();
  print(2);
  await c.future;
}
我认为在第二个示例中,异常应该绑定到完成器的未来,因此在等待未来时也会抛出


有没有一种方法可以将带有完成符的异常延迟到以后的某个时间点?

在中运行第二个示例时,我看到的是

这个错误两次都没有引起注意。这与实际发生的情况相符:

  • 您可以打印
    1
  • 您可以调用
    ()async{c.complete(异常(“hello”);}()
    。这会将一个微任务调度到 完成完成者的未来与例外。然后,调用返回另一个未来,并安排一个微任务,以使用
    null
    完成该未来
  • 然后你等待后一个未来
  • 然后,第一个微任务运行,并在出错的情况下完成完成者的未来。此时,未来没有侦听器,因此错误被视为未捕获,并报告给根区域的未捕获异步错误处理程序。这将打印第一条未捕获的错误行
  • 然后,第二个微任务运行并在另一个将来完成。这使得
    等待
    完成
  • 然后打印
    2
  • 然后你等待完成者的未来。因为未来已经完成,所以这将安排一个微任务,并将此报告给等待者
  • 然后,该微任务运行,第二个等待通过抛出完成者未来的异常来完成
  • 该抛出是未捕获的,因此也报告为未捕获错误
你想要什么还不完全清楚。你是希望完成者的未来在以后完成(如果是的话,多少),还是不希望第一次完成被认为是未完成的

后者更简单,只需执行以下操作:

completer..future.catchError(({})..complete(异常(“hello”));

如果您预先将错误处理程序附加到将来,其中处理(忽略)错误,则未来不会考虑未处理的错误。


(可以说,如果有一种方法可以用一个错误来完成一个补全符,并且事先说它不应该被认为是未经处理的,那就太好了)。

我确实在Mac上的Dart上运行过它,看起来这种行为与web有所不同。在Mac上,程序在第一个错误后存在。预附加看起来不错。事实上,我在一些测试环境中使用了这个构造,在那里我忽略了一些异常,以便稍后(重新)抛出发生的第一个异常。因为Dart缺少一个“向堆栈投掷e”,所以仅仅做“投掷e”就可以松开堆栈。所以我使用“wait Future.error(error,stack)”来传播原始堆栈。未捕获的错误行为在web上是不同的。在本机上,未捕获的错误可以终止整个程序。在web上,您无法终止页面,因此程序会在第一个未捕获错误后继续运行。
import 'dart:async';

Future<void> main() async {
  final c = Completer<void>();
  print(1);
  await (() async => c.completeError(Exception("hello")))();
  print(2);
  await c.future;
}
1
Failed to load ".../x_test.dart": hello
1
Uncaught Error: Exception: hello
2
Uncaught Error: Exception: hello