setInterval 会导致 UI 抖动,因其脱离浏览器 60Hz 渲染节奏、无法感知主线程负载,易引发回调堆积、后台节流失真及高频重排重绘。

直接使用 setInterval 会导致 UI 线程抖动,根本原因在于它与浏览器渲染机制脱节,且无法适应主线程的实际负载状态。
脱离屏幕刷新节奏,帧率不可控
现代显示器通常以 60Hz 刷新(每 16.6ms 一帧),但 setInterval 的回调由定时器线程触发后进入宏任务队列,再等 JS 主线程空闲才执行。它既不感知当前是否处于重绘前的空闲窗口,也不保证每次执行都在帧起点。结果就是:动画更新可能发生在帧中间甚至快结束时,浏览器来不及渲染,只能跳过或合并帧,造成肉眼可见的卡顿和抖动。
主线程阻塞引发回调堆积或延迟
JavaScript 是单线程的,所有 DOM 操作、计算、事件处理都挤在同一线程上。当 setInterval 回调中包含较重逻辑(如频繁修改 scrollTop、批量 DOM 更新),或主线程正被其他任务占用(如图片解码、脚本解析),回调就会排队等待。一旦延迟超过设定间隔,后续回调不会被丢弃,而是连续涌入——出现“一帧内多次更新”或“多帧无更新”,滚动/动画就表现为突兀跳跃或长时间停顿。
后台标签页被节流,时间感知失真
浏览器为节省资源,会对非活跃标签页中的 setInterval 进行强制降频(Chrome 最低限制为 1000ms/次)。用户切回页面时,积压的多个回调会集中执行,导致倒计时猛跳、轮询请求扎堆、滚动位置瞬间归零等异常行为。这种时间漂移让 UI 行为完全脱离真实时间轴,加剧视觉不连贯感。
频繁操作 DOM 触发重排重绘压力
例如用 scrollTop += 1 实现滚动,每毫秒级调用都会触发样式计算、布局、绘制流水线。而 setInterval 缺乏节流机制,容易在极短时间内发起数十次无效布局请求,让渲染线程疲于奔命。GUI 渲染线程和 JS 引擎线程互斥,JS 长时间运行会直接冻结画面更新,进一步放大抖动效果。

















