1. requestAnimationFrame
概念
requestAnimationFrame
是用于创建高性能动画的 API,它的主要特点是与显示器的刷新频率(一般为 60Hz)同步,从而保证动画的流畅性和稳定性。
工作流程
在浏览器渲染一帧时,需要完成以下主要工作:
- 处理用户输入事件:如鼠标、键盘、触摸等操作。
- JavaScript 执行:执行脚本逻辑,更新 DOM 或触发动画。
- 样式计算(Style Calculation):计算元素的样式规则。
- 布局(Layout):重新计算元素的位置和大小。
- 绘制(Paint):将元素绘制为位图。
- 合成(Compositing):将位图组合成最终的屏幕内容。
这些操作需要在 16.66ms 内完成(60FPS)以避免卡顿。
适用场景
- 创建帧率平滑的动画。
- 动态 UI 渲染或复杂过渡效果。
优点
- 高效:避免多余的渲染操作。
- 帧率同步:自动适应不同刷新率的显示器。
代码示例
<canvas id="canvas" width="400" height="200"></canvas>
<script>const canvas = document.getElementById('canvas');const ctx = canvas.getContext('2d');let x = 0;function animate() {ctx.clearRect(0, 0, canvas.width, canvas.height); // 清空画布ctx.fillStyle = 'green';ctx.fillRect(x, 100, 50, 50); // 绘制矩形x += 2;if (x > canvas.width) x = 0; // 循环播放requestAnimationFrame(animate); // 请求下一帧}animate(); // 启动动画
</script>
2. requestIdleCallback
概念
requestIdleCallback
是一个允许在浏览器空闲时间内执行低优先级任务的 API。
工作流程
- 浏览器每帧有固定时间预算(约 16ms)。
- 完成六个主要步骤(事件处理、JavaScript 执行、样式计算、布局、绘制、合成)后,如果时间尚未用尽,浏览器将检测是否存在空闲时间。
- 如果有空闲时间,调用
requestIdleCallback
注册的任务。 - 回调函数接收一个
IdleDeadline
对象,开发者可以基于剩余时间分批完成低优先级任务。
适用场景
- 数据预加载。
- 数据缓存或日志记录。
- 提前加载非关键资源。
优点
- 非阻塞:不影响关键任务。
- 智能调度:根据实际空闲时间分配任务。
代码示例
function handleIdle(deadline) {while (deadline.timeRemaining() > 0 && tasks.length > 0) {const task = tasks.pop();console.log('处理任务:', task);}if (tasks.length > 0) {requestIdleCallback(handleIdle); // 再次请求空闲时间}
}const tasks = Array.from({ length: 10 }, (_, i) => `Task ${i + 1}`);
requestIdleCallback(handleIdle);
3. 两者对比
特性 | requestAnimationFrame | requestIdleCallback |
---|---|---|
核心功能 | 帧同步动画渲染 | 空闲时间任务调度 |
执行时机 | 下一帧刷新前 | 主线程空闲时 |
优先级 | 高 | 低 |
常用场景 | 动画、页面过渡效果 | 缓存预加载、后台计算 |
4. 综合使用建议
- 动画:始终使用
requestAnimationFrame
来实现流畅性。 - 后台任务:优先考虑
requestIdleCallback
,尤其是在处理用户不可见的逻辑时。
这种分工可以帮助开发者构建性能优化的 Web 应用。