UI渲染是事件循环中固定检查点,总在微任务清空后执行;微任务(如Promise.then)必于渲染前完成,DOM变更需经此流程才可见;rAF回调位于微任务之后、渲染之前,用于精确控制动画帧。

UI 渲染在事件循环中不是独立任务,而是固定阶段;微任务则是在宏任务结束后、渲染前立即执行的高优先级队列。两者不属同一层级,不能简单说“谁优先级更高”,而要看它们在循环中的位置关系。
UI 渲染是检查点,不是任务队列
浏览器不会把“渲染”当作一个可排队的宏任务来调度。它只在每轮事件循环结束时进入“渲染检查点”:此时已清空微任务队列,然后判断 DOM/CSS 是否变化、布局是否需更新、是否有动画帧待绘制。若需要,才同步完成样式计算→布局→绘制→合成整套流程。也就是说,渲染时机由浏览器自主决定,且总在微任务之后。
微任务一定在渲染之前执行完毕
这是硬性顺序,不可跳过或延迟:
- 一个宏任务(如点击回调)执行完,调用栈清空
- 立即执行所有已排队的微任务(Promise.then、MutationObserver、queueMicrotask等),直到队列为空
- 此时才进入渲染检查点——微任务执行结果(比如 DOM 修改)已生效,但尚未显示在屏幕上
实际影响:DOM 更新不会立刻可见
你改了 innerHTML 或 class,只是触发了内存中的 DOM 变更,浏览器不会马上重绘。必须等到本轮微任务清空后,进入渲染检查点,才会真正绘制。例如:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
console.log('start');document.body.innerHTML = 'loading...';
Promise.resolve().then(() => {
console.log('microtask');
document.body.innerHTML = 'done';
});
console.log('end');
用户看到页面从原内容 → “loading...” → “done”,中间没有闪烁或空白,因为两次 DOM 修改都在同一渲染帧内被合并处理。
想控制渲染节奏?用 requestAnimationFrame
如果希望某段逻辑严格在下一次屏幕刷新前执行(比如动画关键帧),requestAnimationFrame 回调会在渲染检查点之前、微任务之后被调用。它不属于标准微任务或宏任务,而是渲染阶段的特殊钩子:
- 微任务全部执行完
- 紧接着运行 rAF 回调(如果有)
- 然后才进行真实渲染

















