宏任务执行完毕后立即清空微任务队列,即依次执行所有当前微任务直至队列为空;该过程不可中断,保障Promise链和async/await的及时响应,且仅由宏任务结束(调用栈清空)触发。

宏任务执行完毕后,事件循环的下一步是立即清空当前微任务队列——不是只执行一个,而是把队列里所有微任务依次、不间断地执行完。
为什么必须清空微任务队列?
这是事件循环的硬性规则,不是可选项。JS 引擎在每个宏任务结束后,会强制插入一次微任务检查与执行阶段。只要微任务队列不为空,就持续取出并执行,直到队列变空为止。
- 新注册的微任务(比如在 Promise.then 里又调用了一个 Promise.resolve().then)也会被加入当前队列,并在本轮清空过程中执行
- 这个过程不会被任何宏任务打断,包括刚注册的 setTimeout 或用户点击事件
- 它保障了 Promise 链、async/await 的响应及时性,也避免异步逻辑出现不可预测的延迟
判定机制:如何知道该不该进入微任务阶段?
判定只依赖一个条件:当前宏任务是否已完全执行完毕(即调用栈清空)。一旦满足,引擎立刻转向微任务队列。
- 不看时间、不看队列长度、不等待渲染或其他操作
- 即使微任务队列为空,这一步仍会发生(只是没任务可执行)
- 浏览器环境下,微任务清空后通常会触发一次 UI 渲染(但渲染不是事件循环的一部分,而是渲染线程在 JS 线程空闲时介入)
清空完成后,才进入下一轮循环的起点
微任务队列清空后,事件循环才会从宏任务队列中取出下一个任务(如 setTimeout 回调、DOM 事件回调等),开始新的“宏任务 → 微任务”周期。
- 注意:setTimeout(0) 不是“立即”,它只是尽快入队,仍需等待当前宏任务 + 所有微任务全部完成
- queueMicrotask() 和 Promise.then 的行为一致,都进微任务队列,且优先级相同
- async 函数中 await 后面的代码,会被编译为 Promise.then,所以也属于微任务


















