微任务队列在每次宏任务结束后立即、一次性清空,包括执行中动态产生的新微任务,遵循FIFO顺序,来源包括Promise.then、queueMicrotask、MutationObserver等,共用同一队列。

微任务队列在每次宏任务执行完毕后、下一次宏任务开始前被**立即、一次性清空**——不是“边执行边插入”,也不是“等所有宏任务跑完再统一处理”,而是严格遵循“一个宏任务 → 清空全部当前微任务 → 下一个宏任务”的节奏。
微任务清空发生在宏任务交接处
每当一个宏任务(比如 setTimeout 回调、事件处理函数、script 标签整体代码)执行结束,JS 引擎会立刻检查微任务队列。只要队列非空,就持续取出并执行最前面的微任务,直到队列变空,才允许下一个宏任务入队或执行。
- 哪怕新微任务在执行过程中动态产生(比如 Promise.then 里又 new Promise),也会被加入当前微任务队列末尾,并在本轮继续执行,不会等到下一轮
- 这个过程是“递归清空”:微任务里产生的新微任务,仍属于本轮清空范围
- 注意:微任务队列本身没有“优先级”,只按插入顺序 FIFO 执行
Promise.then 是最典型的微任务入口
Promise 的状态一旦变为 fulfilled 或 rejected,其关联的 then/catch 回调会被作为微任务排入队列,而不是立刻执行。例如:
console.log(1);Promise.resolve().then(() => console.log(2));
console.log(3);
输出是 1 → 3 → 2,因为 Promise.then 的回调被推入微任务队列,等同步脚本(宏任务)执行完才执行。
立即学习“Java免费学习笔记(深入)”;
queueMicrotask 提供手动调度能力
它和 Promise.then 效果一致,但语义更直接:明确告诉引擎“请把这个函数作为微任务执行”。例如:
console.log('a');queueMicrotask(() => console.log('b'));
console.log('c');
输出为 a → c → b。它不依赖 Promise 构造,适合需要轻量、确定性微任务调度的场景(如避免 Promise 构造开销,或统一调度逻辑)。
注意:微任务队列 ≠ Promise 队列
微任务队列包含多种来源:Promise.then/catch/finally、queueMicrotask、MutationObserver 回调、Object.observe(已废弃)等。它们共用同一个队列,按注册顺序混合执行。所以:
- MutationObserver 回调可能插在两个 Promise.then 之间,取决于它们注册的时机
- 不要假设 Promise.then 总是“最先”或“最后”,要看实际入队顺序
- 浏览器保证所有微任务类型都遵循同一套清空规则,不会因类型不同而跳过或延迟


















