浏览器 API性能优化动画
requestAnimationFrame
vs
requestIdleCallback
requestAnimationFrame
rAFVS
requestIdleCallback
rIC兼容性注意:
requestIdleCallback 目前在 Safari 中不受支持。常用 polyfill 方案是用 setTimeout 模拟,或使用 React 的 MessageChannel 方案(即 React Scheduler 的核心原理)。浏览器一帧中的执行顺序
Step 1宏任务队列
setTimeout / setInterval / I/O 回调
每轮事件循环的起点,执行最早排队的宏任务。
Step 2渲染帧
样式计算 → 布局 → 绘制
Step 3requestAnimationFrame
在渲染前执行,与浏览器刷新率同步
Step 4requestIdleCallback
在帧末尾的空闲期执行
对比一览
| 维度 | requestAnimationFrame | requestIdleCallback |
|---|---|---|
| 调用时机 | 每帧渲染前(同步刷新率) | 帧末尾空闲期(不保证何时) |
| 频率 | ≈ 60次/秒(依刷新率) | 不确定,可能几秒才触发一次 |
| 优先级 | 高 — 影响视觉流畅度 | 低 — 可被无限延后 |
| 典型用途 | 动画、Canvas 绘制、滚动 | 预加载、分析、数据同步 |
| 时间控制 | 无内置超时机制 | 支持 timeout 选项 |
| 可见性 | 页面不可见时暂停 | 页面不可见时也可能执行 |
| 取消方式 | cancelAnimationFrame(id) | cancelIdleCallback(id) |
| 兼容性 | ✅ 所有主流浏览器 | ⚠️ 不支持 Safari |
| React 中的使用 | useEffect 中绑定动画 | 内部 Scheduler 基于类似原理 |