微任务队列包含Promise回调、MutationObserver、queueMicrotask及async/await后续代码,其核心判断依据是规范定义的“宏任务尾、渲染前”执行时机,而非代码大小或书写位置。
微任务队列包含的任务类型,核心判断依据是语言标准中明确指定为“microtask”执行时机的异步操作回调。它不取决于代码写在哪、是否看起来“小”,而取决于该回调被引擎如何调度——是否在当前宏任务结束、下一个宏任务开始前,强制清空执行。
以下从三个角度帮你分析识别:
看任务来源是否属于规范定义的微任务源
浏览器和 Node.js 的 JavaScript 引擎(如 V8)严格按 ECMAScript 和 HTML 规范实现微任务调度。常见且确定属于微任务的有:
- Promise 的处理函数:
.then()、.catch()、.finally()的回调函数(注意:Promise 构造器内的 executor 是同步执行的,不算微任务) -
MutationObserver的回调(监听 DOM 变化后触发) -
queueMicrotask(callback)直接入队的函数(ES2020 新增,语义最清晰) -
async/await中await后续的代码(等价于.then(),本质是语法糖)
看执行时机是否满足“宏任务尾、渲染前”这一关键特征
微任务一定在以下节点执行:
- 当前宏任务(比如一次 click 处理、一段 script 执行、一个 setTimeout 回调)刚结束
- 但尚未进入 UI 渲染、也未开始下一个宏任务
这意味着: - 微任务能保证 DOM 更新逻辑(如 Promise.then 里改 class)在页面重绘前生效
- 连续多个微任务会串行执行,中间不会穿插渲染或其它宏任务
- 即使你在
setTimeout(() => {}, 0)里加了Promise.resolve().then(...),后者仍先于setTimeout回调执行
排除常见误判点
- ❌
Promise构造函数里的代码(如new Promise(resolve => { console.log('sync'); resolve() }))是同步执行的,不属于微任务 - ❌
process.nextTick是 Node.js 特有,虽行为类似微任务,但在浏览器环境不存在,也不属于标准微任务(HTML 规范未定义) - ❌
Object.observe已废弃,不应再作为微任务参考 - ❌
requestAnimationFrame属于宏任务(尽管常用于动画,但它在渲染阶段触发,排队逻辑与setTimeout类似)
简单验证方法:写一段混合代码,观察输出顺序。例如:
console.log('1');
Promise.resolve().then(() => console.log('2'));
setTimeout(() => console.log('3'), 0);
console.log('4');
输出一定是 1 → 4 → 2 → 3,其中 2 的位置就印证了它来自微任务队列。
不复杂但容易忽略。











