设计目的
requestAnimationFrame
专为浏览器动画设计,确保回调函数在下一次浏览器重绘前执行,与屏幕刷新率(通常 60Hz,即约 16.7ms/帧)同步,从而实现流畅的动画效果。
setTimeout
通用的延时执行工具,用于在指定毫秒后执行回调,不保证精确性,适用于非动画的异步任务(如延迟加载、一次性操作等)
执行机制
requestAnimationFrame
同步屏幕刷新率:自动匹配设备刷新频率,避免丢帧。
后台暂停:页面隐藏或最小化时自动停止执行,减少资源消耗。
浏览器优化:合并 DOM 操作,减少不必要的重绘和重排。
setTimeout
固定延迟:依赖 JavaScript 事件循环,若主线程阻塞会导致回调延迟。
持续运行:即使页面在后台,仍会执行回调,可能浪费资源。
精度问题:无法保证严格按时执行,长时间任务可能导致累积误差
性能对比
requestAnimationFrame
高效渲染:浏览器自动优化,适合高频更新(如动画)。
节流处理:非激活标签页中的动画会自动降频,节省 CPU/GPU 资源。
setTimeout
潜在性能问题:频繁触发可能导致布局抖动(Layout Thrashing)或过度绘制。
资源浪费:后台任务持续运行,消耗电量与计算资源。
使用场景
requestAnimationFrame
连续动画(CSS 变换、Canvas 绘图、WebGL 渲染)。
需要与屏幕刷新同步的高性能场景。
setTimeout
单次或低频延迟任务(如弹窗提示、定时检查)。
不依赖精确时间控制的异步操作
// requestAnimationFrame(自动计算时间差,实现平滑动画)
function animate() {
element.style.left = (currentPos += 1) + 'px';
requestAnimationFrame(animate);
}
animate();
// setTimeout(需手动控制时间,可能卡顿)
function update() {
element.style.left = (currentPos += 1) + 'px';
setTimeout(update, 16.7); // 近似 60Hz
}
update();
取消执行
requestAnimationFrame:cancelAnimationFrame(id)。
setTimeout:clearTimeout(id)。
参数传递
requestAnimationFrame 回调接收一个高精度时间戳参数。
setTimeout 需手动通过闭包或全局变量传递参数
结论
动画或高频更新场景始终优先使用 requestAnimationFrame,而 setTimeout 更适合非动画的延时逻辑。正确选择工具可显著提升应用性能与用户体验