侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1823 篇文章
  • 累计收到 0 条评论

Dart异步编程:如何正确处理Future与Stream的错误?

2025-12-12 / 0 评论 / 4 阅读

题目

Dart异步编程:如何正确处理Future与Stream的错误?

信息

  • 类型:问答
  • 难度:⭐⭐

考点

异步编程, Future错误处理, Stream错误处理, async/await, 异常捕获

快速回答

在Dart中正确处理异步错误的要点:

  • 使用try/catch捕获async/await中的同步和异步错误
  • Future添加catchError回调处理链式错误
  • 通过Streamlisten方法的onError参数捕获流错误
  • 使用runZonedGuarded捕获未处理的异步异常
  • 避免忽略错误和重复捕获同一异常
## 解析

1. 核心原理

Dart的异步错误处理机制基于事件循环:

  • Future:表示单次异步操作结果,错误通过Future.error或抛出异常产生
  • Stream:处理连续数据流,错误作为独立事件在流中传递
  • 未捕获的异步错误会导致程序终止

2. Future错误处理

方法1:async/await + try/catch

void fetchData() async {
  try {
    var data = await http.get('https://api.example.com/data');
    print('Data: $data');
  } catch (e, s) {
    print('Error: $e');
    print('Stack trace: $s');
  }
}

方法2:catchError回调

http.get('https://api.example.com/data')
  .then((data) => print('Data: $data'))
  .catchError((e, s) {
    print('Future error: $e');
    print('Stack trace: $s');
  });

3. Stream错误处理

Stream countStream() async* {
  for (int i = 0; i < 5; i++) {
    if (i == 3) throw Exception('Stream error at $i');
    yield i;
  }
}

void main() {
  countStream().listen(
    (data) => print('Received: $data'),
    onError: (e, s) => print('Stream error: $e'),
    cancelOnError: false  // 错误后是否继续监听
  );
}

4. 全局错误捕获

void main() {
  runZonedGuarded(() {
    Future.error('Uncaught async error');
  }, (error, stack) {
    print('Global error: $error');
  });
}

5. 最佳实践

  • 优先使用async/await:使异步代码更接近同步风格
  • 始终捕获根异常:避免使用空的catch块
  • 记录堆栈跟踪:通过StackTrace参数获取错误源头
  • 区分错误类型:针对不同异常采取不同恢复策略

6. 常见错误

  • ❌ 忽略catchError导致未处理异常
  • ❌ 在then中抛出异常但未后续处理
  • ❌ 混淆同步try/catch与异步错误捕获范围
  • ❌ 未处理StreamSubscription的取消逻辑导致内存泄漏

7. 扩展知识

  • Error vs Exception:Dart中所有错误均继承自Error,但通常用Exception表示可恢复错误
  • Isolate错误:跨Isolate通信需通过SendPort发送错误对象
  • StreamController:手动添加错误事件controller.addError(error)