Promise回调优先于queueMicrotask,后者又优先于MutationObserver;三者同属微任务但插入位置不同:Promise回调入队首,queueMicrotask居中,MutationObserver批量入队尾。

Promise 回调和 MutationObserver 回调虽然都属于微任务,但它们在微任务队列中**不是平等排队**的——存在明确的插入顺序与执行优先级差异。
Promise 回调总在队列前端执行
只要 Promise 状态已确定(fulfilled 或 rejected),调用 .then()、.catch() 或 .finally() 时,其回调会立即被推入微任务队列的**最前面**。这意味着:
- 同一轮微任务中,Promise 回调一定先于 MutationObserver 执行
- 即使 MutationObserver 已监听到 DOM 变更并准备入队,只要 Promise 回调已注册,它就会抢占先机
- 多个 Promise 链式调用(如
p.then().then().then())会按注册顺序依次加入队列前端,严格串行执行
MutationObserver 回调默认排在队列末尾
MutationObserver 的回调不是“每次 DOM 变更就立刻入队一个”,而是等本轮同步代码结束后、在清空微任务队列前,将**所有待处理的变更记录批量打包**,再作为一个或多个微任务推入队列**尾部**。所以:
- 它天然让位于 Promise、
queueMicrotask等更“即时”的微任务 - 即便 DOM 在 Promise 回调里被修改,Observer 的响应也只会出现在下一轮微任务执行阶段的末尾
- 这种设计避免了频繁 DOM 操作触发大量 Observer 回调,造成渲染阻塞或逻辑混乱
queueMicrotask 是可控的中间选择
queueMicrotask() 提供了一种显式调度微任务的方式,它的插入位置介于 Promise 和 MutationObserver 之间:
- 比 Promise 回调略晚(不抢前端),但比 MutationObserver 早(不落队尾)
- 适合需要比 Promise 后、又比 Observer 更早执行的逻辑,比如清理副作用、触发轻量状态同步
- 在兼容性允许的环境下(Chrome 71+/Safari 12.1+/Edge 79+),它是替代
setTimeout(..., 0)的更优方案
实际执行顺序可验证
以下代码能清晰体现三者竞争关系:
console.log('1');
Promisere.resolve().then(() => console.log('2'));
queueMicrotask(() => console.log('3'));
const observer = new MutationObserver(() => console.log('4'));
observer.observe(document.body, { childList: true });
document.body.appendChild(document.createElement('div'));
console.log('5');
输出一定是:1 → 5 → 2 → 3 → 4。这印证了微任务内部也有层级:Promise 最快,queueMicrotask 居中,MutationObserver 最慢但更稳。


















