await 不阻塞主线程,而是暂停 async 函数并将后续代码作为微任务调度,待 Promise settled 后恢复执行;它自动包装非 Promise 值、仅作用于当前函数、错误由 Promise 状态驱动。

await 关键字不是让 JavaScript 线程“停下来等”,而是让当前 async 函数暂停执行流,把控制权交还给事件循环,等右侧的 Promise 状态 settled(fulfilled 或 rejected)后,再从暂停处恢复——整个过程不阻塞主线程,页面依然可交互、定时器照常触发、其他微任务和宏任务正常调度。
它依赖微任务队列实现“暂停”与恢复
当引擎遇到 await 时,并不会冻结 JS 执行栈。它实际做了三件事:
- 记录当前 async 函数的暂停位置(类似状态机快照)
- 将 await 后续代码包装成回调,推入微任务队列(microtask queue)
- 立即退出当前函数,返回一个 pending 的 Promise,清空调用栈
等 Promise 完成后,引擎会在本轮宏任务结束、下一轮宏任务开始前,从微任务队列中取出该回调并执行,从而“恢复”函数后续逻辑。
await 后面不必须是 Promise,但等待效果取决于值类型
JS 会自动对非 Promise 值调用 Promise.resolve() 包装:
立即学习“Java免费学习笔记(深入)”;
-
await 42→ 立即 resolve,后续代码在下一个微任务执行(有“暂停感”,但无真实延迟) -
await fetch('/api')→ 真正异步,需等待网络响应完成才恢复 -
await { then: resolve => resolve('ok') }→ 只要对象有then方法(thenable),就能被 await 处理
若右侧值既不是 Promise 也没有 then 方法(如 await null),就直接当作同步值返回,函数仍会进入微任务阶段再执行下一行——这容易被误认为“没生效”,其实是机制使然。
它只作用于当前 async 函数内部
await 的顺序保证仅限于单个 async 函数内:
- 多个 await 按书写顺序串行执行:
await api1(); await api2(); - 不同 async 函数之间互不影响,彼此独立调度
- 想并行发起请求,应先启动所有 Promise,再统一 await:
const [a, b] = await Promise.all([api1(), api2()]);
它不能跨函数同步,也不能改变事件循环本身的调度规则——宏任务(如 setTimeout)、微任务(如 Promise.then)、渲染帧仍按原有优先级运行。
错误处理由 Promise 状态驱动
await 表达式本身不捕获错误,而是将 Promise 的 rejection 直接抛出:
-
await Promise.reject('fail')会中断函数执行,除非用 try/catch 包裹 - 未捕获的 rejection 会让整个 async 函数返回一个 rejected Promise
- 这和
.catch()行为一致,只是写法更贴近同步逻辑
也就是说,await 的“暂停”始终绑定在 Promise 生命周期上,它的存在意义是把异步链的嵌套结构,转为线性可读的语句序列,而非改变 JavaScript 的单线程非阻塞本质。


















