Promise 和 async/await 的区别是什么?如何捕获异步错误?

一、Promise 与 async/await 的核心区别

1. 设计定位与语法结构
  • Promise

  • 是 ES6 引入的异步容器对象,代表未来完成的操作结果,状态不可逆(Pending → Fulfilled/Rejected)。

  • 链式调用:通过 .then() 处理成功结果、.catch() 捕获错误、.finally() 执行清理逻辑。
    javascript fetchData() .then(data => process(data)) .catch(err => console.error(err));

  • 缺点

  • 链式调用在复杂逻辑中易形成“回调地狱”(视觉嵌套);

  • 中间值传递需通过嵌套作用域实现,代码冗余。

    • async/await
  • 是 ES2017 基于 Promise 的语法糖,用同步写法实现异步逻辑。

  • 同步风格async 标记函数返回 Promise,await 暂停执行直至 Promise 完成:
    javascript async function getData() { const data = await fetchData(); // 等待 Promise 完成 return process(data); }

  • 优势

  • 代码线性化,消除嵌套;

  • 直接使用变量存储中间结果。

2. 执行流程差异
场景Promiseasync/await
创建后代码执行同步代码继续执行,不阻塞await 暂停所在函数,释放调用栈
回调触发时机回调进入微任务队列,当前任务后执行await 后代码在 Promise 完成后执行
错误传播需手动链式调用 .catch()可通过 try/catch 直接捕获

示例对比

// Promise:后续代码立即执行
const p = fetchData(); 
console.log("继续执行"); // 先输出
p.then(data => console.log(data));

// async/await:函数内暂停
async function main() {
  const data = await fetchData(); // 此处暂停
  console.log(data);             // 后输出
}
console.log("继续执行");          // 先输出
3. 可读性与调试
  • Promise
  • 调试器无法逐步跟踪 .then() 链;
  • 错误堆栈可能缺失上下文。
    • async/await
  • 支持同步式断点调试;
  • 错误堆栈包含完整函数调用链。

二、异步错误捕获方法

1. Promise 的错误捕获

.catch() 方法:链式调用末尾捕获错误。

fetchData()
  .then(data => process(data))
  .catch(err => console.error("全局捕获:", err)); // 捕获链中任意错误
  • 注意事项

  • 未处理的 Promise 错误会导致 “UnhandledPromiseRejection” ;

  • 异步回调中抛错(如 setTimeout)无法被 .catch() 捕获:
    javascript new Promise((resolve) => { setTimeout(() => { throw new Error("异步错误"); }, 1000); }).catch(err => console.log(err)); // 无法捕获!

2. async/await 的错误捕获

try/catch 块:仿同步代码捕获错误。

async function loadData() {
  try {
    const data = await fetchData();
    const result = await process(data);
  } catch (err) {
    console.error("操作失败:", err); // 捕获所有 await 错误
  } finally {
    cleanUp(); // 必执行逻辑
  }
}

并行错误处理:结合 Promise.all() + try/catch

async function fetchMulti() {
  try {
    const [user, posts] = await Promise.all([
      fetchUser(), 
      fetchPosts()
    ]);
  } catch (err) {
    console.error("并行请求出错:", err); // 任一失败即捕获
  }
}
3. 关键实践建议
  • 避免混合使用
  • 在 async 函数中无需再用 .then(),直接用 await 简化。
    • 全局兜底
  • 浏览器中监听 unhandledrejection 事件捕获未处理的 Promise 错误:
    javascript window.addEventListener("unhandledrejection", e => { console.error("未捕获的Promise错误:", e.reason); e.preventDefault(); // 阻止控制台报错 });

三、如何根据场景选择?

场景推荐方案原因
简单异步链(<3 步)Promise 链式调用代码简洁,无需额外函数封装
复杂逻辑(依赖中间值、错误分支)async/await + try/catch逻辑线性化,错误集中处理
并行独立任务Promise.all() + await最大化并发效率,统一错误捕获
需取消的异步操作第三方库(如 RxJS)原生 Promise 和 async/await 均不支持取消

总结

  • 核心区别
    Promise 是基础异步模型,通过状态机和链式调用管理异步;async/await 是其语法增强,以同步写法提升可读性和可维护性。
  • 错误捕获
    Promise 依赖 .catch() 链式捕获,async/await 通过 try/catch 实现结构化错误处理,后者更符合直觉。
  • 演进关系
    async/await 本质上仍是 Promise,但通过语法层优化解决了 Promise 在复杂场景下的工程化痛点。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

破碎的天堂鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值