微任务是在当前同步脚本执行完毕后、下一个宏任务开始前立即清空整个队列的真实任务,典型来源包括promise回调、mutationobserver和queuemicrotask();其执行时机早于宏任务且保证队列完全清空。

微任务(Microtask)在事件循环中不是“占位符”,而是有明确执行时机的真实任务队列。它会在当前同步脚本执行完毕后、下一个宏任务(Macrotask)开始前,**清空整个微任务队列**——这是关键行为,不是占位或延迟,而是强制、立即、连续执行。
微任务的典型来源
以下操作会向微任务队列添加任务:
-
Promises:
then、catch、finally的回调 - MutationObserver:DOM 变化监听的回调
- queueMicrotask():显式插入自定义微任务(ES2024 标准方法)
代码示例:清晰展示执行顺序
下面这段代码能直观体现微任务如何“插队”在宏任务之间:
js<br>console.log('1');<br><br>setTimeout(() => console.log('2'), 0); // 宏任务(下一轮事件循环)<br><br>Promise.resolve().then(() => console.log('3')); // 微任务(本轮末尾)<br>Promise.resolve().then(() => console.log('4')); // 微任务(同上,排队执行)<br><br>queueMicrotask(() => console.log('5')); // 微任务(同上)<br><br>console.log('6');<br>
输出结果为:1 → 6 → 3 → 4 → 5 → 2
说明:所有同步代码(1 和 6)先执行;接着一次性清空微任务队列(3、4、5);最后才轮到 setTimeout 的宏任务(2)。
对比宏任务,突出微任务特性
微任务与宏任务(如 setTimeout、setInterval、I/O、UI 渲染)的核心区别在于:
- 微任务总在**当前任务结束、渲染/下个宏任务开始前**执行,且**队列会被完全清空**(即使新微任务在执行中被加入,也会继续执行)
- 宏任务每次只执行一个,之后必须让出控制权,可能触发渲染或处理其他事件
- 不要用微任务“模拟延时”——它不推迟执行,只是提前抢占;需要真实延迟请用
setTimeout(fn, 0)或Promise.resolve().then(fn).then(...)链式分拆(但语义不同)
一个易错点:微任务中的 Promise 会继续产生微任务
注意这个嵌套行为:
js<br>Promise.resolve().then(() => {<br> console.log('A');<br> Promise.resolve().then(() => console.log('B'));<br>});<br>
输出是 A → B,因为内层 then 产生的新微任务,仍属于本轮微任务清空过程,会紧接着执行。











