最小可重现代码:
Future<void> foo() async => throw Future.error('Foo');
void main() {
foo().catchError(print);
}
Run Code Online (Sandbox Code Playgroud)
我仍然在控制台上看到此错误
Dart 未处理的异常:Foo,堆栈跟踪:
如果我抛出FlutterError(...),错误会被捕获但Future.error(...)会失败。原因是出现的错误本身就是 a Future,但我该如何处理呢?
您的代码中有两个问题:
事实上,在第一个事件发生之前,您async标记的方法实际上并没有真正作为事件队列上的另一个事件运行。await
在这种情况下,这意味着在我们有时间分配任何错误处理之前实际上已抛出异常,因此我们会收到错误。此行为可以在以下文档中找到catchError:
请注意,Future 不会延迟报告错误,直到添加侦听器为止。如果第一个 catchError (或 then)调用发生在该 future 完成并出现错误之后,则该错误将被报告为未处理的错误。
https://api.dart.dev/stable/2.12.2/dart-async/Future/catchError.html
解决这个问题的方法是在await抛出异常之前实际创建一个,所以让我们这样做:
Future<void> foo() async {
await Future<void>.value();
throw Future.error('Foo');
}
void main() {
foo().catchError(print);
}
Run Code Online (Sandbox Code Playgroud)
但我们现在得到以下错误作为输出,我们需要调查:
Future<void> foo() async {
await Future<void>.value();
throw Future.error('Foo');
}
void main() {
foo().catchError(print);
}
Run Code Online (Sandbox Code Playgroud)
这是来自尝试打印错误的方法的Instance of 'Future<dynamic>'一行。print正如我们所看到的,我们在这里得到了一个Future对象。这个对象实际上是从创建的对象Future.error('Foo')。
在 Dart 中,我们可以得到throw任何我们想要的对象。在async标记方法中,该对象将被打包在Future.error. 所以就你而言,你实际上所做的是Future.error(Future.error('Foo'))。
然后,您将处理外部错误,而不是内部错误。如果我们这样做:
Future<void> foo() async {
await Future<void>.value();
throw Future.error('Foo');
}
Future<void> main() async {
await foo().catchError((Object obj) => (obj as Future).catchError(print));
}
Run Code Online (Sandbox Code Playgroud)
这将返回:
Instance of 'Future<dynamic>'
Unhandled exception:
Foo
Run Code Online (Sandbox Code Playgroud)
由于我们现在正在catchError调用Future由Future.error('Foo').