requestAnimationFrame 和 setTimeout / setInterval 有什么区别?为什么页面动画优先用 rAF,而倒计时 / 轮询有时反而用 setTimeout?

三者的本质区别

维度 requestAnimationFrame setTimeout setInterval
触发时机 浏览器每次重绘前(与刷新率同步,通常 60fps) 至少等待指定毫秒后(宏任务) 每隔指定毫秒(宏任务)
后台标签页 自动暂停(省电、不空转) 被节流到 >=1s 被节流到 >=1s
精度 与渲染帧对齐,动画最顺滑 受事件循环阻塞、易抖动 同上,且可能「丢帧堆叠」
适合场景 视觉动画、滚动、逐帧渲染 单次延时、轮询、倒计时 固定间隔重复(不推荐做动画)

为什么动画优先用 rAF

// ✅ 平滑动画:每帧根据时间戳计算进度,与屏幕刷新同步
function animate(el) {
  let start
  function step(ts) {
    if (!start) start = ts
    const p = (ts - start) / 1000        // 已过去秒数
    el.style.transform = 'translateX(' + (p * 200) + 'px)'
    if (p < 1) requestAnimationFrame(step)
  }
  requestAnimationFrame(step)
}

如果用 setInterval(fn, 16),定时器与渲染帧不一定对齐,容易掉帧卡顿,且在后台标签页仍持续运行浪费资源。

为什么倒计时 / 轮询有时用 setTimeout

关键判断:视觉动画 → rAF;真实时间 / 轮询 / 与帧无关的节奏 → setTimeout / setInterval。

注意事项

同分类其他题目