JavaScript事件循环中微任务统一排队于单一队列,按调度时间顺序执行,而非类型分组;Promise.then、queueMicrotask等均入同一队列尾部,嵌套调度追加至队列末尾,Promise构造函数内代码同步执行。

JavaScript 的 Event Loop 中,微任务(microtask)排队遵循“先进先出”原则,但不同来源的微任务在同一个微任务队列中是**统一排队、统一执行**的,并非各自独立队列。关键点在于:Promise 回调和 queueMicrotask 回调都进入**同一个微任务队列**,按它们被调度(schedule)的**时间顺序**排队,而不是按类型分组。
微任务队列是单一的,不是按类型分隔
规范中只定义了一个微任务队列(microtask queue)。无论你调用:
Promise.resolve().then(...)queueMicrotask(() => {...})-
await后续处理(本质也是 Promise 微任务) - MutationObserver 回调(也属于微任务)
它们都会被插入到**同一个队列末尾**,按插入顺序依次执行。没有“Promise 队列”或“queueMicrotask 队列”之分。
调度时机决定排队顺序,不是代码书写顺序
谁先被“调度”,谁就排在前面。例如:
立即学习“Java免费学习笔记(深入)”;
console.log(1); Promise.resolve().then(() => console.log(2)); queueMicrotask(() => console.log(3)); console.log(4); // 输出:1 → 4 → 2 → 3
说明:Promise.then 的回调先于 queueMicrotask 被调度(因为 Promise.resolve() 执行更早),所以 2 排在 3 前面。
但如果反过来:
console.log(1); queueMicrotask(() => console.log(2)); Promise.resolve().then(() => console.log(3)); console.log(4); // 输出:1 → 4 → 2 → 3
这里 queueMicrotask 先被调用,所以 2 排在 3 前面 —— 完全取决于哪一行代码先执行。
嵌套调度会追加到队列尾部,不插队
在微任务中再调度新微任务,新任务一定排在当前正在执行的微任务之后,且排在当前队列剩余任务之后。例如:
queueMicrotask(() => {
console.log('a');
queueMicrotask(() => console.log('b'));
});
Promise.resolve().then(() => console.log('c'));
// 输出:a → c → b
解释:初始队列是 [a 的回调, c 的回调];执行 a 时,queueMicrotask('b') 把 b 加入队列尾 → 新队列为 [c, b];接着执行 c,再执行 b。
注意:Promise 构造函数内的同步代码不属于微任务
很多人误以为 new Promise((resolve) => { console.log('sync') }) 是微任务 —— 实际上它完全同步执行。只有 .then、.catch、.finally 回调,以及 resolve/reject 触发后的链式响应,才进入微任务队列。
例如:
console.log('start');
new Promise(r => {
console.log('promise sync');
r();
});
console.log('end');
// 输出:start → promise sync → end(无微任务输出)
要触发微任务,必须使用 .then 等后续操作。


















