await 不暂停线程,而是暂停 async 函数执行流,交还控制权给事件循环,依赖微任务队列在 promise settled 后恢复;它要求上下文为 async 函数或顶层模块,自动解包 thenable 并返回 fulfilled 值或抛出 rejected 错误。

await 并不真正暂停线程或阻塞执行,而是“暂停当前 async 函数的执行流程”,把控制权交还给事件循环,等待 Promise 解决后自动恢复后续代码。
它暂停的是“async 函数内部的执行流,不是整个程序”
JavaScript 是单线程、非阻塞的。await 不会让 CPU 等待、不会冻结页面、也不会挂起线程。它只是告诉引擎:“我现在要等一个 Promise,你先别执行我后面的语句,去处理别的任务(比如响应点击、渲染动画、处理其他 Promise),等这个 Promise settled(fulfilled 或 rejected)了,再回来继续从这行往下走。”
这背后依赖的是微任务队列(microtask queue):当 await 遇到一个 pending 的 Promise,函数立即退出(返回一个 pending 的 Promise),当前调用栈清空;等该 Promise 完成时,引擎会在本轮事件循环末尾、下一轮宏任务前,把恢复 async 函数的回调推入微任务队列。
await 后面必须是 thenable,但不一定是 Promise
await 实际上会尝试调用右侧值的 then 方法(即“thenable 检查”)。所以你可以 await:
- 原生 Promise(最常见)
- 任何带
then方法的对象(如 jQuery 的 Deferred、Axios 的响应对象) - 普通值(如
await 42)——会被自动包装成Promise.resolve(42),立刻 resolve
注意:await null 或 await undefined 也会被包装,但若对象没有 then 方法且不是 Promise,就直接当作同步值处理,不会“等待”。
await 总是返回 Promise 的 fulfilled 值(或抛出 rejected 错误)
无论你 await 的是什么,表达式本身的结果总是 Promise 成功后的值(resolved value):
-
const data = await fetch('/api').then(r => r.json())→data是解析后的 JSON 对象 -
await Promise.reject('oops')→ 直接抛出错误,需 try/catch 捕获 -
await Promise.all([p1, p2])→ 返回一个数组,包含所有 fulfilled 结果
也就是说,await 是“解包器”:它把 Promise 的异步语义“抹平”,让你用同步写法拿到最终结果(或面对异常)。
它依赖 async 函数上下文,不能在任意地方使用
await 只能在 async function 内部或顶层模块(Top-level await)中使用。这是因为:
- async 函数会被编译为状态机,每个 await 点都是一个暂停/恢复的检查点
- 引擎需要维护执行上下文(如变量环境、await 暂停位置)来支持恢复
- 普通函数没有这套机制,强行写 await 会语法报错
例如:function foo() { await delay(1000); } ❌ 报错;必须写成 async function foo() { await delay(1000); } ✅











