await 暂停 async 函数但不阻塞主线程,错误仅在 await 等待被 reject 的 Promise 时才被 try-catch 捕获;串行 await 任一失败即中断后续,Promise.all 并行则全启动且一拒即整体拒。

在 JavaScript 中,try-catch 块内使用 await 时,执行顺序由 Promise 状态和事件循环共同决定,并非简单“同步阻塞”。关键点是:await 会暂停当前 async 函数的执行,但不会阻塞主线程;错误只有在 Promise 被 reject 且未被 await 捕获时,才会冒泡到 try-catch。
await 的暂停与恢复机制
await 实际上是语法糖,等价于将后续代码包装进 .then()。遇到 await promise 时:
- 若
promise已 resolve 或 reject(即已 settled),await 立即取得值或抛出错误,进入try或catch分支 - 若
promise还处于 pending 状态,当前 async 函数暂停,控制权交还事件循环,待 promise settle 后,通过微任务队列恢复执行 - 恢复后的行为取决于 promise 结果:resolve → 赋值继续执行;reject → 抛出异常,触发
catch
错误捕获的边界:await 是关键开关
不是所有异步错误都会被 try-catch 捕获,必须用 await 显式等待 Promise,错误才能被 try-catch 捕获:
- ✅ 正确:
try { const data = await fetch('/api').then(r => r.json()); }—— await 等待整个链,reject 会被 catch - ❌ 错误:
try { fetch('/api').then(r => r.json()); }—— 无 await,Promise 异步错误脱离 try-catch 作用域,变成未处理 rejection - ⚠️ 注意:多个 await 按顺序执行,前一个未 catch 的 reject 会中断后续 await(除非显式处理)
常见陷阱:并行 await 与顺序 await 的差异
多个 await 默认是串行的,但可改造成并行以提升性能,此时错误处理逻辑不同:
- 串行写法:
await a(); await b(); await c();—— 任一 reject,后续不执行,错误直接进 catch - 并行写法:
await Promise.all([a(), b(), c()]);—— 全部同时启动;只要一个 reject,Promise.all就 reject,整体进 catch - 容错并行:
const [ra, rb, rc] = await Promise.all([a().catch(e => e), b().catch(e => e), c().catch(e => e)]);—— 每个 promise 自行捕获错误,不会中断整体流程
调试建议:善用 await + 变量解构与错误分类
为清晰追踪哪一步出错,推荐结构化 await 并区分错误类型:
- 对关键步骤单独 await 并命名变量,便于定位:
const user = await getUser(id); const profile = await getProfile(user.id); - 在 catch 中检查 error 类型(如
error instanceof TypeError或error.status),避免“一锅端”处理 - 必要时用
finally做清理(如关闭 loading 状态),它在 resolve 和 reject 后都执行

















