queueMicrotask 是将回调插入当前微任务队列末尾的原生 API,比 setTimeout(0) 更早执行,因其属微任务而非宏任务;它轻量、语义清晰,适用于 DOM 更新前逻辑、避免递归爆栈等场景。

queueMicrotask 是一个专门用于将回调函数插入当前微任务队列末尾的原生 API,它比 setTimeout(fn, 0) 更早执行,因为后者属于宏任务(macrotask),而前者明确属于微任务(microtask)。
为什么 queueMicrotask 比 setTimeout(0) 更早执行
JavaScript 的事件循环中,每次宏任务执行完后,会清空整个微任务队列(包括 Promise.then、MutationObserver 回调、queueMicrotask 注入的任务等),然后才进入下一个宏任务。而 setTimeout(fn, 0) 即使延迟为 0,仍被归入宏任务队列,需等待当前任务 + 所有微任务完成后才执行。
- 当前同步代码 → 执行完毕
- 立即运行所有已排队的微任务(含 queueMicrotask 回调)
- 再取下一个宏任务(如 setTimeout、setInterval、I/O 回调)
基本用法与典型场景
调用方式非常简单:传入一个无参函数即可。
queueMicrotask(() => {
console.log('我在本轮微任务末尾执行');
});
console.log('我先打印');
// 输出顺序:
// 我先打印
// 我在本轮微任务末尾执行
常见适用场景包括:
- 在 DOM 渲染前批量更新状态后,确保视图更新前完成逻辑(配合
requestAnimationFrame可更精细控制) - 避免同步递归爆栈,又不想退到下一轮事件循环(比如实现轻量级异步迭代器)
- 封装 Promise 逻辑时,绕过 Promise 构造器开销,直接调度微任务
与 Promise.resolve().then() 的区别
两者都进入微任务队列,但 queueMicrotask 更轻量:
- 不创建 Promise 实例,无内存分配和状态管理开销
- 不涉及 Promise 链式处理、错误捕获或 thenable 解析逻辑
- 语义更清晰:就是“我要在本轮微任务最后跑一段代码”
例如:
// 等价但更简洁 queueMicrotask(() => doSomething()); // 功能相同,但多了一层 Promise 包装 Promise.resolve().then(() => doSomething());
注意事项与兼容性
queueMicrotask 在现代浏览器(Chrome 71+、Firefox 71+、Safari 15.4+、Edge 79+)及 Node.js 11.0+ 中已原生支持。若需兼容旧环境,可用降级方案:
const safeQueueMicrotask = typeof queueMicrotask === 'function' ? queueMicrotask : fn => Promise.resolve().then(fn);
注意不要在微任务中无限调用 queueMicrotask,否则会导致事件循环无法进入宏任务,页面卡死或 Node.js 进程无响应。










