侧边栏壁纸
博主头像
colo

欲买桂花同载酒

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

Dart异步编程:Future与async/await的异常处理

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

题目

Dart异步编程:Future与async/await的异常处理

信息

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

考点

异步编程,异常处理,Future,async/await

快速回答

在Dart异步编程中处理异常的关键点:

  • 使用try/catch包裹await调用捕获同步和异步异常
  • 通过.catchError()处理Future链式调用中的异常
  • 避免在async函数中遗漏未处理的异常
  • 使用Future.error()主动抛出异步异常
## 解析

问题场景

在Dart异步编程中,以下代码可能无法正确捕获异常:

Future<void> fetchData() async {
  final data = await http.get('https://api.example.com/data');
  print('Data: ${data.body}');
}

void main() {
  try {
    fetchData();
  } catch (e) {
    print('Caught: $e');  // 无法捕获异步异常
  }
}

请解释原因并提供三种正确的异常处理方案。

原理说明

Dart的异步异常处理机制:

  • 同步异常:立即抛出,可通过try/catch捕获
  • 异步异常:存储在Future中,需通过注册回调或await捕获
  • async函数自动将同步异常包装为Future.error
  • 未捕获的异步异常会导致程序终止

解决方案

方案1:在async函数内部使用try/catch

Future<void> fetchData() async {
  try {
    final data = await http.get('https://api.example.com/data');
    print('Data: ${data.body}');
  } catch (e) {
    print('Internal catch: $e');  // 捕获await抛出的异常
  }
}

方案2:使用Future.catchError()

void main() {
  fetchData().catchError((e) {
    print('External catch: $e');  // 捕获Future链中的异常
  });
}

方案3:结合await与try/catch

void main() async {
  try {
    await fetchData();  // await将异步异常转为同步异常
  } catch (e) {
    print('Await catch: $e');
  }
}

最佳实践

  • async函数中始终用try/catch包裹可能出错的await调用
  • 为所有公开的异步API添加.catchError()处理
  • 使用Future.error()传递结构化错误信息:
    Future.error({'code': 404, 'message': 'Not found'})
  • 避免在catch块中返回null,应返回合理的默认值或重新抛出

常见错误

  • 错误1:在非async函数中尝试用try/catch捕获异步调用
    // 错误示例 try { Future.delayed(Duration(seconds: 1), () => throw Exception()); } catch (e) {} // 无法捕获
  • 错误2:忽略async*生成器中的异常处理
  • 错误3:在catchError后忘记返回恢复值导致链中断

扩展知识

  • Zone:使用runZonedGuarded全局捕获异步异常
    runZonedGuarded(() {
      fetchData();
    }, (error, stack) {
      print('Global catch: $error');
    });
  • 错误类型:区分Exception(可预期)和Error(程序错误)
  • 空安全:异步返回类型应明确声明可空性
    Future<String?> fetchNullableData()