微任务在当前宏任务结束后立即全部执行完毕,因其队列采用清空式执行机制:宏任务结束即检查并持续执行微任务直至队列为空,期间不进行渲染或响应事件。

微任务在当前宏任务结束后“立即全部执行完毕”,不是靠魔法,而是由 JavaScript 引擎严格按规则调度的结果。关键在于:**微任务队列是“清空式”执行的——只要它不为空,引擎就不会去取下一个宏任务,也不会让出主线程。**
微任务为什么能“全部立即执行”?
这背后是事件循环(Event Loop)的硬性流程约束:
- 每个宏任务(比如整个
<script></script>标签、一次点击回调)执行完后,引擎会强制暂停宏任务调度 - 紧接着,它检查微任务队列;如果非空,就按先进先出(FIFO)顺序逐个取出并执行,直到队列彻底为空
- 这个过程不中断、不插队、不渲染、不响应新事件——哪怕中间又产生了新的微任务(比如某个
then里又调用了Promise.resolve().then()),也会被追加到当前队列末尾并继续执行
哪些操作会触发微任务入队?
常见来源包括:
-
Promise.then/catch/finally回调(状态变更时触发) -
queueMicrotask(callback)(ES2020 明确 API,语义最清晰) -
MutationObserver的回调(DOM 变动后) - Node.js 中的
process.nextTick(优先级比 Promise 还高,仅限 Node)
一个典型执行链说明“全部执行”的含义
看这段代码:
console.log('A');Promisepromise1'); }).then(() => { console.log('promise2'); });
queueMicrotask(() => console.log('micro1'));
console.log('B');
输出一定是:A → B → promise1 → promise2 → micro1。注意:promise2 是 promise1 回调里产生的新微任务,但它仍会在本轮被拉出来执行——这就是“清空”的实际表现。
它和 UI 渲染、用户交互的关系
微任务执行期间,浏览器不会重绘页面、不响应鼠标点击、不处理键盘输入。所有这些都要等到微任务队列完全清空、且引擎进入“可能渲染”阶段之后才发生。这也是为什么大量嵌套 Promise.then 可能导致界面卡顿——它们挤占了本该用于渲染或响应的时间片。


















