侧边栏壁纸
博主头像
colo

欲买桂花同载酒

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

Promise链式调用与async/await的异常处理

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

题目

Promise链式调用与async/await的异常处理

信息

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

考点

Promise链式调用,async/await异常处理,错误传播机制

快速回答

在Promise链中,错误会跳过后续的then直到被catch捕获。使用async/await时:

  • 必须用try/catch处理同步错误
  • 异步错误需在Promise调用处捕获
  • 未捕获的Promise拒绝会导致全局错误
## 解析

问题场景

以下代码在用户点击按钮时执行异步操作,分析错误处理缺陷:

// 模拟API请求
const fetchData = () => new Promise((resolve, reject) => {
  setTimeout(() => reject('Network error'), 100);
});

// 有缺陷的执行函数
async function handleClick() {
  const data = fetchData(); // 缺少await
  try {
    console.log(data.result); // 尝试读取undefined属性
  } catch (e) {
    console.log('Caught:', e);
  }
}

// 按钮点击触发
document.getElementById('btn').addEventListener('click', handleClick);

错误分析

  • 错误1:缺少await - fetchData()返回Promise但未等待,导致data是Pending状态的Promise对象
  • 错误2:错误类型混淆 - try/catch只能捕获同步错误,无法捕获异步Promise拒绝
  • 错误3:全局未处理拒绝 - 未处理的Promise拒绝可能导致应用崩溃

正确解决方案

async function handleClick() {
  try {
    const data = await fetchData(); // 正确等待Promise
    console.log(data.result);
  } catch (e) {
    console.error('Request failed:', e);
    // 实际项目应添加用户提示
  }
}

// 全局兜底错误处理
window.addEventListener('unhandledrejection', event => {
  console.error('Unhandled rejection:', event.reason);
  event.preventDefault(); // 阻止默认控制台报错
});

核心原理

  • Promise错误冒泡:拒绝状态的Promise会跳过后续then直到遇见catch
  • async/await本质:async函数返回Promise,await会暂停执行直到Promise状态变更
  • 错误捕获差异
    • 同步错误:try/catch可直接捕获
    • 异步错误:只能通过Promise.catch或async函数内的try/catch捕获

最佳实践

  1. 始终在await的Promise外包裹try/catch
  2. 在Promise链末尾添加catch作为兜底
  3. 使用window.addEventListener('unhandledrejection')全局监控未处理错误
  4. 对于并行操作,用Promise.allSettled()替代Promise.all()确保所有请求完成

常见陷阱

错误写法问题修复方案
const res = fetchData(); 未等待异步结果 添加await
promise.then().catch()内使用async 嵌套异步导致错误处理复杂化 统一使用async/await语法
在循环中忽略await 并行/串行执行混乱 明确使用Promise.all()for...of

扩展知识

  • Top-level await:ES2022支持在模块顶层使用await,但需注意阻塞风险
  • 错误边界(React):前端框架通常提供组件级错误捕获机制
  • AbortController:配合fetch可实现请求超时和取消