不要再傻傻使用 requestAnimationFrame 啦!!!
之前我寫了一個埋點庫 sunshine-track ,很多人問我為啥批量上報埋點信息的時候,用的是 requestIdleCallback 而不是 requestAnimationFrame,今天就解答一下。
sunshine-track 源碼學習:https://github.com/sanxin-lin/sunshine-track。
一、背景與問題場景
在前端性能監控領域,埋點信息上報是重要的數據收集手段。當我們需要批量上報用戶行為數據時,傳統同步上報方案可能導致以下問題:
- 阻塞主線程造成頁面卡頓
- 影響關鍵渲染流程的執行
- 造成不必要的性能損耗
二、核心API對比分析
1. requestAnimationFrame(rAF)
執行時機:每次重繪前(約16.6ms/次)
設計目的:執行與渲染相關的動畫邏輯
優先級:高(屬于瀏覽器渲染流水線的一部分)
特點:
- 保證與屏幕刷新率同步
- 頁面隱藏時自動暫停
2. requestIdleCallback(rIC)
執行時機:瀏覽器空閑時段
設計目的:執行低優先級任務
優先級:低(僅在空閑時執行)
特點:
- 提供deadline參數判斷剩余時間
- 頁面隱藏時可能不會執行
- 可設置超時時間強制執行
三、選擇 requestIdleCallback 的核心原因
1. 執行時機的合理性
- 埋點上報是非關鍵任務,不需要搶占渲染資源
- 避免在渲染關鍵路徑中插入網絡I/O操作
- 適合利用瀏覽器的空閑時段執行
2. 優先級控制
- 用戶交互 > 動畫渲染 > 空閑任務
- rAF屬于高優先級(每幀必須執行)
- rIC屬于低優先級(可被瀏覽器跳過)
3. 性能影響對比
指標 | rAF方案 | rIC方案 |
主線程阻塞概率 | 較高 | 極低 |
影響FPS的可能性 | 可能 | 無 |
CPU使用率 | 較高 | 優化空間大 |
執行可靠性 | 高 | 需超時處理 |
4. 容錯機制
四、特殊場景處理建議
1. 頁面關閉前的上報
2. 兼容性處理
使用 polyfill 方案:
3. 超時控制策略
五、最佳實踐總結
- 分優先級處理:關鍵數據立即上報,普通數據批量處理
- 隊列機制:積累足夠數據或達到時間閾值時觸發
- 混合策略:結合 rIC + 超時機制 + 降級方案
- 性能監控:記錄上報任務執行耗時
- 錯誤重試:對失敗請求進行指數退避重試
六、結論
選擇 requestIdleCallback 的核心優勢在于其能夠:
- 最大限度減少對用戶體驗的影響
- 智能利用瀏覽器空閑時段
- 實現優先級合理的任務調度
- 避免與關鍵渲染流程競爭資源