面试追问:"除了 Promise,还有哪些微任务?"
本文用 3 分钟 + 3 个实战,带你吃透 queueMicrotask 与 MutationObserver。
一、queueMicrotask:最轻量微任务
1️⃣ 语法
js
queueMicrotask(() => {
console.log('我在本轮微任务队列末尾执行');
});
2️⃣ 特点
- 优先级 :高于
setTimeout
、低于Promise.then
- 浏览器支持:Chrome 71+、Edge 79+、Safari 12.1+
- 用途 :把非 Promise 逻辑塞进微任务队列,避免阻塞渲染
3️⃣ 实战:防抖里的微任务
js
function microDebounce(fn) {
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => {
queueMicrotask(() => fn(...args));
}, 300);
};
}
比
setTimeout(...,0)
更快,0.2 ms 内执行。
二、MutationObserver:DOM 变化的"间谍"
1️⃣ 语法
js
const observer = new MutationObserver(mutations => {
mutations.forEach(m => console.log(m));
});
observer.observe(targetNode, {
childList: true, // 监听子节点增删
subtree: true, // 监听后代
attributes: true, // 监听属性变化
attributeOldValue: true
});
2️⃣ 特点
- 微任务执行:DOM 变更 → 微任务队列 → 回调
- 性能友好 :批量 DOM 变化一次性处理,0 次回流
3️⃣ 实战:无限滚动加载
html
<div id="list"></div>
<div id="sentinel">↑ 触发加载 ↑</div>
<script>
const observer = new MutationObserver(() => {
const sentinel = document.getElementById('sentinel');
if (sentinel && isInViewport(sentinel)) {
loadMore();
}
});
observer.observe(document.body, { childList: true, subtree: true });
</script>
4️⃣ 实战:自动保存编辑器内容
js
const editor = document.querySelector('#editor');
const observer = new MutationObserver(() => {
localStorage.setItem('draft', editor.innerHTML);
});
observer.observe(editor, { childList: true, subtree: true });
三、组合连招:微任务里监听 DOM
js
queueMicrotask(() => {
new MutationObserver(() => {
console.log('DOM changed in microtask');
}).observe(document, { childList: true });
});
执行顺序:DOM 变更 → MutationObserver → queueMicrotask → Promise.then → 渲染
四、一句话总结
- queueMicrotask :把任何逻辑塞进微任务队列末尾------快、轻、无 UI 阻塞
- MutationObserver :DOM 变化后微任务触发------批量、0 回流、性能王者