You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dart多异步抛出引发未处理异常,如何捕获全部异常?

如何捕获所有异步调用抛出的异常?

你的推测完全正确。当await future1抛出异常时,asyncMethod会立即终止执行,不会走到await future2这一步。但future2在之前已经被创建并启动,它抛出的异常没有任何代码去监听处理,因此会成为未处理异步异常,导致程序后续报错。

以下是几种确保捕获所有异步异常的解决方案:

方案1:使用Future.wait统一处理并行Future的异常

Future.wait可以同时等待多个并行执行的Future,通过不同的写法可以实现不同的异常处理逻辑:

方式A:捕获首个异常(默认行为)

Future.wait默认会在第一个Future失败时立即抛出异常,适合只需要知道是否有失败的场景:

import 'dart:async';

Future<bool> asyncFuncThatThrows(Duration duration, String message) {
  return Future.delayed(
      duration, () => throw Exception('$message asyncFuncThatThrows'));
}

Future<void> asyncMethod() async {
  print('asyncMethod start');
  final futures = [
    asyncFuncThatThrows(Duration(seconds: 0), 'first '),
    asyncFuncThatThrows(Duration(seconds: 0), 'second '),
  ];
  print('asyncMethod -> functions that throw executed');
  
  try {
    await Future.wait(futures);
  } catch (e) {
    print('Caught error in asyncMethod: $e');
  }
  
  print('asyncMethod done');
}

void main() async {
  try {
    print('Start');
    await asyncMethod();
  } catch (e) {
    print('Try/Catch in main: $e');
  }
  print('Done');
}

方式B:捕获所有异常

如果需要收集并处理所有Future的异常,给每个Future单独添加catchError处理,确保没有未处理异常:

Future<void> asyncMethod() async {
  print('asyncMethod start');
  final futures = [
    asyncFuncThatThrows(Duration(seconds: 0), 'first ')
        .catchError((e) => print('Handled first error: $e')),
    asyncFuncThatThrows(Duration(seconds: 0), 'second ')
        .catchError((e) => print('Handled second error: $e')),
  ];
  print('asyncMethod -> functions that throw executed');
  
  await Future.wait(futures);
  
  print('asyncMethod done');
}

这种方式下所有Future的异常都会被单独处理,不会出现未处理异常,asyncMethod也能正常执行到结束。

方案2:串行await并逐个处理异常

如果不需要并行执行Future,可以逐个await并给每个异步调用单独添加try-catch,前一个失败不会影响后一个的执行:

Future<void> asyncMethod() async {
  print('asyncMethod start');
  print('asyncMethod -> functions that throw executed');
  
  try {
    await asyncFuncThatThrows(Duration(seconds: 0), 'first ');
  } catch (e) {
    print('Caught first error: $e');
  }
  
  try {
    await asyncFuncThatThrows(Duration(seconds: 0), 'second ');
  } catch (e) {
    print('Caught second error: $e');
  }
  
  print('asyncMethod done');
}

方案3:用带错误回调的runZoned捕获全局未处理异常

你之前使用的runZoned没有生效,是因为缺少onError回调。配置该回调后,可以捕获Zone内所有未处理的异步异常:

void main() {
  runZoned(() async {
    try {
      print('Start');
      await asyncMethod();
    } catch (e) {
      print('Try/Catch in main: $e');
    }
    print('Done');
  }, onError: (e, stackTrace) {
    print('Caught by runZoned: $e');
    print('Stack trace: $stackTrace');
  });
}

关于DartPad无未处理异常的疑问

DartPad的运行环境默认配置了全局异常捕获机制,会自动处理未处理的异步异常并隐藏报错输出;而本地Dart运行时没有这个默认处理,因此会显示完整的未处理异常栈信息。


内容的提问来源于stack exchange,提问作者Alvaro Mateo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 17:15:18