微任务队列在当前宏任务结束后、下一个宏任务开始前被彻底清空,且浏览器通常在微任务全部执行完毕后才进行一次ui渲染;利用该机制可批量更新dom、避免多次强制重排,用queuemicrotask包裹dom写入操作可确保更新可见后再执行后续逻辑,并与requestanimationframe协同实现帧率稳定、响应及时的渲染优化。

微任务队列在当前宏任务结束后、下一个宏任务开始前被**彻底清空**,且浏览器通常会在微任务全部执行完毕后,才进行一次 UI 渲染(重排+重绘)。这个确定性的时序,正是优化 DOM 渲染的关键支点。
批量更新 DOM,避免多次强制重排
连续修改同一元素的多个样式或结构,若同步执行,可能触发多次布局计算。把它们统一收拢到一个微任务中,就能让浏览器只做一次重排重绘。
- 用 Promise.resolve().then() 或 queueMicrotask() 包裹所有 DOM 写入操作
- 同一次事件循环内多次调用,仍只产生一个微任务执行时机,内部可合并状态或取最终值
- 避免在微任务里读取 offsetHeight、getBoundingClientRect() 等布局信息——这会强制同步计算,破坏聚合效果
确保 DOM 更新可见后再执行后续逻辑
比如你插入了一个提示框,希望用户能立刻看到,再自动关闭。如果用 setTimeout 关闭,可能因渲染被延迟而出现“闪一下就没了”;改用微任务,就能保证插入已生效、渲染已完成。
- 插入 DOM 后,立即用 queueMicrotask(() => { /* 关闭逻辑 */ })
- 比 Promise.then 更轻量,语义更清晰:就是“等这次同步结束、渲染前执行”
- 不依赖时间参数,不受定时器精度或队列积压影响
与 requestAnimationFrame 协同,对齐渲染帧
微任务虽快,但不绑定帧率。若高频触发,可能挤占 rAF 时间,导致掉帧。最佳组合是:微任务收集中间状态 + rAF 执行最终写入。
- 收集所有待更新数据(如位置、类名、文本)放在内存中,用微任务去重或合并
- 在 requestAnimationFrame 回调中一次性应用到真实 DOM
- 既避开同步布局抖动,又确保更新落在浏览器渲染周期内,帧率更稳
替代 setTimeout(0) 做“让出控制权”
传统用 setTimeout(0) 把逻辑推迟到下一轮,实际要等完整宏任务周期,中间还可能穿插其他宏任务(如用户输入、网络回调),响应不及时。
- 用 queueMicrotask 替代,逻辑在当前同步代码之后、渲染之前执行,延迟最短
- 适合需要快速响应但又不能阻塞主线程的场景,例如表单校验反馈、按钮防抖状态切换
- 不会触发渲染,也不创建 Promise 对象,开销更低











