async/await 的异常处理是深度耦合 promise 状态、微任务调度与 try-catch 的执行机制,await 隐式绑定 catch 回调,错误中断当前函数但不阻塞其他任务,finally 总会执行(不可 await),未捕获错误触发 unhandledrejection。

async/await 的异常处理不是语法糖的“表面装饰”,而是和 Promise 状态流转、微任务调度、try-catch 语义深度耦合的执行机制。它不靠魔法,靠的是 JavaScript 引擎对 Promise 拒绝路径的自动绑定与事件循环的精确协同。
await 实际触发 Promise.catch 绑定
当你写 await fetch('/api'),引擎并非简单“等结果”,而是将后续代码(即 await 后面的所有语句)包装成一个微任务,并隐式为该 Promise 注册了 .catch() 回调——这个回调就对应你外层的 catch 块。
- 如果 fetch 返回的 Promise 被 reject,引擎立即跳转到 catch 块,传入 rejection 值作为
error参数 - 若未写 try-catch,该 rejection 会直接导致整个 async 函数返回的 Promise 进入 rejected 状态
- 这和手写
fetch().then(...).catch(...)在语义上完全等价,只是由语法自动完成
错误不会跨 await “传染”,但会中断当前函数流程
每个 await 是独立的 Promise 监听点。前一个 await 抛错,不会影响后一个 await 的执行机会——因为函数在抛错时已退出,后续代码根本不会走到。
- 错误只终止当前 async 函数的剩余执行,不阻塞其他宏任务或微任务
- 例如:
await api1(); await api2();中 api1 失败,api2 不会发起;但页面其他 setTimeout 或点击事件照常响应 - 想让多个请求“互不干扰”,需单独 try-catch 每个 await,或用
Promise.allSettled
finally 块始终执行,且在 catch 之后
无论 await 是否成功、是否被 catch 捕获,只要 async 函数开始执行,finally 就保证运行——它是清理资源(如关闭 loading、释放锁)的可靠位置。
- 执行顺序固定:try →(成功)→ finally;或 try →(失败)→ catch → finally
- 即使 catch 块里再 throw 新错误,finally 仍会先执行完,再把新错误向上冒泡
- 注意:finally 中不能用 await,否则会打断“最终保障”的语义(它应同步完成)
顶层未捕获错误会落入 unhandledrejection
当 async 函数返回的 Promise 被 reject,且没有任何 .catch() 或 try-catch 处理时,浏览器会触发 unhandledrejection 事件。
- 这是最后的兜底信号,可用于日志上报或降级提示
- Node.js 中类似事件是
unhandledRejection,需主动监听避免进程退出 - 它说明:错误没被任何 JS 层逻辑接手,不是“没发生”,而是“没人管”
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











