高优先级任务应使用queuemicrotask,在同步代码结束后、渲染前执行,延迟低于0.1ms;它比promise.then更轻量、比settimeout(0)更及时,适合状态聚合与表单校验,但需避免递归调用导致饥饿。

高优先级任务要在用户感知最敏感的时机执行,比如输入响应、动画更新或首屏渲染。关键不是“抢时间”,而是让任务落在事件循环中真正低延迟、不阻塞渲染的位置。
用 queueMicrotask 做即时响应
这是调度高优任务最直接的方式。它把回调插入当前微任务队列末尾,保证在同步代码结束后、任何宏任务(包括渲染)之前执行,延迟通常低于 0.1ms。
- 适合场景:状态聚合(如多次 input 更新合并为一次 re-render)、防抖中间态清理、表单校验反馈
- 比 Promise.then 更轻量——不创建 Promise 实例,无额外内存开销
- 比 setTimeout(fn, 0) 更及时——不进宏任务队列,避免被其他 setTimeout 或事件回调插队
避开宏任务竞争,不依赖 setTimeout(0)
setTimeout(fn, 0) 看似“立刻”,实际受浏览器最小间隔限制(通常 ≥ 4ms),且会排队到宏任务队列末尾。当页面正密集触发 click、scroll 或 requestAnimationFrame 时,它可能被压后几十毫秒。
- 不要用它处理用户交互反馈(如按钮点击后的 loading 状态切换)
- 若必须用宏任务(例如需要等渲染完成后再操作 DOM),改用 requestAnimationFrame —— 它对齐浏览器刷新节奏,比 setTimeout 更精准
- 高优任务一旦进了宏任务队列,就失去了“本轮控制权”,容易被长任务或大量事件拖慢
组合使用:微任务 + 渲染钩子
真正关键的任务往往需要“在状态更新后、UI 绘制前”执行,比如计算 layout、同步滚动位置或触发 CSS 动画。
- 先用 queueMicrotask 批量更新数据或标记变更
- 再用 requestAnimationFrame 读取 layout 并应用视觉效果(避免强制同步重排)
- 这样既保证逻辑及时,又不打断渲染流水线
警惕微任务饥饿,别递归调用
queueMicrotask 回调里再调自己,会导致微任务队列无限增长,阻塞后续所有任务(包括渲染和事件处理)。
- 正确做法:用标志位 + 循环消费队列,例如维护一个 pendingTasks 数组,在单次 microtask 中批量执行
- 可配合 MutationObserver 监听 DOM 变更,作为高优任务的补充触发点(尤其适合响应式框架内部)
- 对特别敏感的操作(如 pointermove 追踪),考虑用 passive 事件监听器 + requestIdleCallback 降级兜底
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











