async/await 本身不直接进入微任务队列,而是通过 Promise 状态变化触发 then 回调入队;async 函数立即返回 pending Promise,await 后代码本质是微任务回调,与 Promise.then 同优先级、同调度规则。

async/await 本身不直接“进入”微任务队列,而是通过 Promise 的状态变化,触发其 then 回调被推入微任务队列——这才是它实际参与事件循环调度的关键环节。
async 函数返回值立即包装成 Promise
声明一个 async 函数时,它会立刻返回一个 pending 状态的 Promise,无论函数体是否含 await。这个 Promise 的 resolve 值就是函数的 return 值(或 undefined),reject 值则是抛出的错误。
- 函数内部同步代码仍按顺序执行,属于当前宏任务的一部分
- return 表达式会被 Promise.resolve() 包装;throw 语句则触发 Promise.reject()
- 即使没有 await,async 函数也自带一层 Promise 封装
await 暂停执行,但不阻塞线程
遇到 await 后,如果右侧表达式已是一个 fulfilled 或 rejected 的 Promise,JavaScript 引擎会立即提取其结果,并把 await 后面的语句(即 async 函数剩余逻辑)封装为一个微任务回调,加入微任务队列。
- await 并不是“等待”时间,而是“注册后续逻辑到微任务队列”的信号
- 引擎不会挂起整个线程,而是让出控制权,继续执行当前宏任务中其余同步代码
- 若 await 的 Promise 还在 pending 状态,函数暂停;一旦它 settle(fulfill/reject),对应微任务即被排入队列
await 后的代码本质是微任务回调
每个 await 表达式之后的语句,在底层都会被编译器转化为 Promise.then() 的回调形式。因此,它们天然属于微任务范畴。
- 多个 await 会形成链式微任务:第一个 await 完成后,触发第二个 await 的准备逻辑(仍属微任务)
- 即使连续写 await fetch('/a'); await fetch('/b');,第二个请求也只在第一个响应解析完毕后才发起
- 这种串行行为源于微任务的“清空式执行”:前一个微任务跑完,才轮到下一个,中间不插入宏任务
与 Promise.then 的调度完全一致
async/await 是语法糖,它生成的微任务和手写的 Promise.then 回调处于同一队列、享有同等优先级,遵循相同规则:
- 当前宏任务结束后,立即批量执行所有待处理微任务(包括 await 后续、then 回调、queueMicrotask 等)
- 微任务之间无抢占,也不会被 setTimeout、setInterval 中断
- UI 渲染发生在微任务清空之后、下一个宏任务开始之前

















