JavaScript 中 requestAnimationFrame 在后台标签页不触发的问题排查与替代方案
做数据大屏或者定时轮询渲染的时候,很容易遇到一个现象:页面切到后台再切回来,某些依赖于 requestAnimationFrame 的动画或状态更新会「卡住」几秒,甚至像是什么都没发生。浏览器为了省电和降低 CPU,在标签页不可见时会暂停 requestAnimationFrame 的回调,把它降频甚至完全冻结。但业务里可能用它来驱动非纯视觉任务,比如轮询状态、计算布局、播放帧序列,这时候就出问题了。下面从一次实际排查过程说起,看看为什么会这样,以及除了切回页面强制刷新外,还有哪些更可控的写法。 ## 问题复现 假设有一个组件用 rAF 来做一个平滑的数字滚动,同时每帧检查一下远程任务是否完成。 ```js function startLoop() { let last = performance.now(); function frame(now) { const delta = now - last; if (delta > 16) { renderNumber(); checkTaskStatus(); last = now; } requestAnimationFrame(frame); } requestAnimationFrame(frame); } ``` 在浏览器里正常切换标签页后,`checkTaskStatus` 不会执行,等回来时又恢复正常。如果任务完成依赖这个轮询,用户切走再回来可能发现状态还停在旧数据上。 ## 为什么后台标签页没回调 规范里没有规定 rAF 在页面不可见时应该继续以 60fps 运行。实际情况是,大多数浏览器在文档进入 hidden 状态后,会把 rAF 回调挂起,或者降低到非常低的频率(比如 1fps 甚至 0)。因为 rAF 的本意是配合屏幕刷新,不可见的页面没有刷新需求,继续运行等于白白耗电。 可以用 `document.visibilityState` 验证: ```js let count = 0; function tick() { count++; console.log('frame', count, document.visibilityState); requestAnimationFrame(tick); } requestAnimationFrame(tick); ``` 在后台标签页停几秒再切回来,控制台里帧数几乎不增长。这不是 bug,是节能策略。 ## 如果只是做动画,应该怎么做 纯视觉动画在页面不可见时暂停是合理的,用户看不到,继续跑也没意义。如果希望切回来时从当前状态继续,而不是「时间跳变」,可以用时间戳计算差值,而不是依赖帧数累加。 ```js let startTime = null; function animate(now) { if (startTime === null) startTime = now; const elapsed = now - startTime; const progress = Math.min(elapsed / 1000, 1); element.style.transform = `translateX(${progress * 200}px)`; if (progress { checkTaskStatus(); }, 1000); } function stopPolling() { if (timer) clearInterval(timer); timer = null; } ``` 如果任务对时效性要求更高,可以在 `visibilitychange` 里做补偿:切回页面时立即执行一次。 ```js document.addEventListener('visibilitychange', () => { if (document.visibilityState === 'visible') { checkTaskStatus(); } }); ``` ## 后台仍然需要执行的场景 有些逻辑必须持续运行,比如 WebSocket 心跳、音频处理、Web Worker 里的计算。这些不应该依赖主线程的 rAF。常见做法是把逻辑放进 Worker,Worker 的定时器不会被页面可见性冻结(但可能被浏览器整体节流策略影响,至少不受 visibility 直接控制)。 ```js // worker.js setInterval(() => { self.postMessage('heartbeat'); }, 5000); // main.js const worker = new Worker('worker.js'); worker.onmessage = (e) => { if (e.data === 'heartbeat') { sendHeartbeat(); } }; ``` WebSocket 心跳也可以直接用 `setInterval` 在页面里发,切后台时浏览器可能降低频率,但多数情况下不会完全停止。真正完全停止的情况出现在移动端切到桌面或锁屏,这时只能靠 Service Worker 或原生推送补足。 ## 兼容旧代码的折中处理 如果项目里已经大量使用了 rAF 做非视觉逻辑,全部重写成本高。可以在封装层加一个开关,在页面隐藏时改用 `setInterval` 兜底,可见时再切回 rAF。 ```js class FrameLoop { constructor(callback, fallbackInterval = 1000) { this.callback = callback; this.fallbackInterval = fallbackInterval; this.rafId = null; this.timer = null; this.onVisibilityChange = this.onVisibilityChange.bind(this); document.addEventListener('visibilitychange', this.onVisibilityChange); this.start(); } start() { this.stop(); if (document.visibilityState === 'visible') { const loop = () => { this.callback(); this.rafId = requestAnimationFrame(loop); }; this.rafId = requestAnimationFrame(loop); } else { this.timer = setInterval(() => this.callback(), this.fallbackInterval); } } stop() { if (this.rafId) cancelAnimationFrame(this.rafId); if (this.timer) clearInterval(this.timer); this.rafId = null; this.timer = null; } onVisibilityChange() { this.start(); } destroy() { this.stop(); document.removeEventListener('visibilitychange', this.onVisibilityChange); } } ``` 这样既保留了可见时的帧同步,又保证后台不会完全停止响应。回调里要注意不要做太重的事情,因为兜底间隔可能只有 1 秒,堆积起来反而更卡。 理解 rAF 的节能行为之后,选型就清晰了:画面相关用它,定时任务用定时器,必须后台运行的放 Worker。切页面的卡顿大多不是代码写错,而是把两种不同目的的东西混在了一起。 推荐查看天气:http://www.362tq.com/wangcang/zuotian.html 推荐查看天气:http://www.362tq.com/wangcang/7tian.html 推荐查看天气:http://www.362tq.com/wangcang/10tian.html 推荐查看天气:http://www.362tq.com/wangcang/15tian.html 推荐查看天气:http://www.362tq.com/wangcang/40tian.html 推荐查看天气:http://www.362tq.com/qingchuan/ 推荐查看天气:http://www.362tq.com/qingchuan/zuotian.html 推荐查看天气:http://www.362tq.com/qingchuan/7tian.html 推荐查看天气:http://www.362tq.com/qingchuan/10tian.html 推荐查看天气:http://www.362tq.com/qingchuan/15tian.html 推荐查看天气:http://www.362tq.com/qingchuan/40tian.html 推荐查看天气:http://www.362tq.com/jiange/ 推荐查看天气:http://www.362tq.com/jiange/zuotian.html 推荐查看天气:http://www.362tq.com/jiange/7tian.html 推荐查看天气:http://www.362tq.com/jiange/10tian.html 推荐查看天气:http://www.362tq.com/jiange/15tian.html 推荐查看天气:http://www.362tq.com/jiange/40tian.html 推荐查看天气:http://www.362tq.com/cangxi/ 推荐查看天气:http://www.362tq.com/cangxi/zuotian.html 推荐查看天气:http://www.362tq.com/cangxi/7tian.html 推荐查看天气:http://www.362tq.com/cangxi/10tian.html 推荐查看天气:http://www.362tq.com/cangxi/15tian.html 推荐查看天气:http://www.362tq.com/cangxi/40tian.html 推荐查看天气:http://www.362tq.com/suining/ 推荐查看天气:http://www.362tq.com/suining/zuotian.html 推荐查看天气:http://www.362tq.com/suining/7tian.html 推荐查看天气:http://www.362tq.com/suining/10tian.html 推荐查看天气:http://www.362tq.com/suining/15tian.html 推荐查看天气:http://www.362tq.com/suining/40tian.html 推荐查看天气:http://www.362tq.com/chuanshan/ 推荐查看天气:http://www.362tq.com/chuanshan/zuotian.html 推荐查看天气:http://www.362tq.com/chuanshan/7tian.html 推荐查看天气:http://www.362tq.com/chuanshan/10tian.html 推荐查看天气:http://www.362tq.com/chuanshan/15tian.html 推荐查看天气:http://www.362tq.com/chuanshan/40tian.html 推荐查看天气:http://www.362tq.com/anju/ 推荐查看天气:http://www.362tq.com/anju/zuotian.html 推荐查看天气:http://www.362tq.com/anju/7tian.html 推荐查看天气:http://www.362tq.com/anju/10tian.html 推荐查看天气:http://www.362tq.com/anju/15tian.html 推荐查看天气:http://www.362tq.com/anju/40tian.html 推荐查看天气:http://www.362tq.com/pengxi/ 推荐查看天气:http://www.362tq.com/pengxi/zuotian.html 推荐查看天气:http://www.362tq.com/pengxi/7tian.html 推荐查看天气:http://www.362tq.com/pengxi/10tian.html 推荐查看天气:http://www.362tq.com/pengxi/15tian.html 推荐查看天气:http://www.362tq.com/pengxi/40tian.html 推荐查看天气:http://www.362tq.com/shehong/ 推荐查看天气:http://www.362tq.com/shehong/zuotian.html 推荐查看天气:http://www.362tq.com/shehong/7tian.html 推荐查看天气:http://www.362tq.com/shehong/10tian.html 推荐查看天气:http://www.362tq.com/shehong/15tian.html 推荐查看天气:http://www.362tq.com/shehong/40tian.html 推荐查看天气:http://www.362tq.com/daying/ 推荐查看天气:http://www.362tq.com/daying/zuotian.html 推荐查看天气:http://www.362tq.com/daying/7tian.html 推荐查看天气:http://www.362tq.com/daying/10tian.html 推荐查看天气:http://www.362tq.com/daying/15tian.html 推荐查看天气:http://www.362tq.com/daying/40tian.html 推荐查看天气:http://www.362tq.com/neijiang/ 推荐查看天气:http://www.362tq.com/neijiang/zuotian.html 推荐查看天气:http://www.362tq.com/neijiang/7tian.html 推荐查看天气:http://www.362tq.com/neijiang/10tian.html 推荐查看天气:http://www.362tq.com/neijiang/15tian.html 推荐查看天气:http://www.362tq.com/neijiang/40tian.html 推荐查看天气:http://www.362tq.com/dongxing/ 推荐查看天气:http://www.362tq.com/dongxing/zuotian.html 推荐查看天气:http://www.362tq.com/dongxing/7tian.html 推荐查看天气:http://www.362tq.com/dongxing/10tian.html 推荐查看天气:http://www.362tq.com/dongxing/15tian.html 推荐查看天气:http://www.362tq.com/dongxing/40tian.html 推荐查看天气:http://www.362tq.com/najiangweiyuan/ 推荐查看天气:http://www.362tq.com/najiangweiyuan/zuotian.html 推荐查看天气:http://www.362tq.com/najiangweiyuan/7tian.html 推荐查看天气:http://www.362tq.com/najiangweiyuan/10tian.html 推荐查看天气:http://www.362tq.com/najiangweiyuan/15tian.html 推荐查看天气:http://www.362tq.com/najiangweiyuan/40tian.html 推荐查看天气:http://www.362tq.com/zizhong/ 推荐查看天气:http://www.362tq.com/zizhong/zuotian.html 推荐查看天气:http://www.362tq.com/zizhong/7tian.html 推荐查看天气:http://www.362tq.com/zizhong/10tian.html 推荐查看天气:http://www.362tq.com/zizhong/15tian.html 推荐查看天气:http://www.362tq.com/zizhong/40tian.html 推荐查看天气:http://www.362tq.com/longchang/ 推荐查看天气:http://www.362tq.com/longchang/zuotian.html 推荐查看天气:http://www.362tq.com/longchang/7tian.html 推荐查看天气:http://www.362tq.com/longchang/10tian.html 推荐查看天气:http://www.362tq.com/longchang/15tian.html 推荐查看天气:http://www.362tq.com/longchang/40tian.html 推荐查看天气:http://www.362tq.com/leshan/ 推荐查看天气:http://www.362tq.com/leshan/zuotian.html 推荐查看天气:http://www.362tq.com/leshan/7tian.html 推荐查看天气:http://www.362tq.com/leshan/10tian.html 推荐查看天气:http://www.362tq.com/leshan/15tian.html 推荐查看天气:http://www.362tq.com/leshan/40tian.html 推荐查看天气:http://www.362tq.com/shizhong/ 推荐查看天气:http://www.362tq.com/shizhong/zuotian.html 推荐查看天气:http://www.362tq.com/shizhong/7tian.html 推荐查看天气:http://www.362tq.com/shizhong/10tian.html 推荐查看天气:http://www.362tq.com/shizhong/15tian.html 推荐查看天气:http://www.362tq.com/shizhong/40tian.html 推荐查看天气:http://www.362tq.com/wutongqiao/ 推荐查看天气:http://www.362tq.com/wutongqiao/zuotian.html 推荐查看天气:http://www.362tq.com/wutongqiao/7tian.html 推荐查看天气:http://www.362tq.com/wutongqiao/10tian.html 推荐查看天气:http://www.362tq.com/wutongqiao/15tian.html 推荐查看天气:http://www.362tq.com/wutongqiao/40tian.html 推荐查看天气:http://www.362tq.com/jinkouhe/ 推荐查看天气:http://www.362tq.com/jinkouhe/zuotian.html 推荐查看天气:http://www.362tq.com/jinkouhe/7tian.html 推荐查看天气:http://www.362tq.com/jinkouhe/10tian.html 推荐查看天气:http://www.362tq.com/jinkouhe/15tian.html 推荐查看天气:http://www.362tq.com/jinkouhe/40tian.html 推荐查看天气:http://www.362tq.com/jianwei/ 推荐查看天气:http://www.362tq.com/jianwei/zuotian.html 推荐查看天气:http://www.362tq.com/jianwei/7tian.html 推荐查看天气:http://www.362tq.com/jianwei/10tian.html 推荐查看天气:http://www.362tq.com/jianwei/15tian.html 推荐查看天气:http://www.362tq.com/jianwei/40tian.html 推荐查看天气:http://www.362tq.com/jingyan/ 推荐查看天气:http://www.362tq.com/jingyan/zuotian.html 推荐查看天气:http://www.362tq.com/jingyan/7tian.html 推荐查看天气:http://www.362tq.com/jingyan/10tian.html 推荐查看天气:http://www.362tq.com/jingyan/15tian.html 推荐查看天气:http://www.362tq.com/jingyan/40tian.html 推荐查看天气:http://www.362tq.com/jiajiang/ 推荐查看天气:http://www.362tq.com/jiajiang/zuotian.html 推荐查看天气:http://www.362tq.com/jiajiang/7tian.html 推荐查看天气:http://www.362tq.com/jiajiang/10tian.html 推荐查看天气:http://www.362tq.com/jiajiang/15tian.html 推荐查看天气:http://www.362tq.com/jiajiang/40tian.html 推荐查看天气:http://www.362tq.com/muchuan/ 推荐查看天气:http://www.362tq.com/muchuan/zuotian.html 推荐查看天气:http://www.362tq.com/muchuan/7tian.html 推荐查看天气:http://www.362tq.com/muchuan/10tian.html 推荐查看天气:http://www.362tq.com/muchuan/15tian.html 推荐查看天气:http://www.362tq.com/muchuan/40tian.html 推荐查看天气:http://www.362tq.com/ebian/ 推荐查看天气:http://www.362tq.com/ebian/zuotian.html 推荐查看天气:http://www.362tq.com/ebian/7tian.html 推荐查看天气:http://www.362tq.com/ebian/10tian.html 推荐查看天气:http://www.362tq.com/ebian/15tian.html 推荐查看天气:http://www.362tq.com/ebian/40tian.html 推荐查看天气:http://www.362tq.com/mabian/ 推荐查看天气:http://www.362tq.com/mabian/zuotian.html 推荐查看天气:http://www.362tq.com/mabian/7tian.html 推荐查看天气:http://www.362tq.com/mabian/10tian.html 推荐查看天气:http://www.362tq.com/mabian/15tian.html 推荐查看天气:http://www.362tq.com/mabian/40tian.html 推荐查看天气:http://www.362tq.com/emeishan/ 推荐查看天气:http://www.362tq.com/emeishan/zuotian.html 推荐查看天气:http://www.362tq.com/emeishan/7tian.html 推荐查看天气:http://www.362tq.com/emeishan/10tian.html 推荐查看天气:http://www.362tq.com/emeishan/15tian.html 推荐查看天气:http://www.362tq.com/emeishan/40tian.html 推荐查看天气:http://www.362tq.com/nanchong/ 推荐查看天气:http://www.362tq.com/nanchong/zuotian.html 推荐查看天气:http://www.362tq.com/nanchong/7tian.html 推荐查看天气:http://www.362tq.com/nanchong/10tian.html 推荐查看天气:http://www.362tq.com/nanchong/15tian.html 推荐查看天气:http://www.362tq.com/nanchong/40tian.html 推荐查看天气:http://www.362tq.com/shunqing/ 推荐查看天气:http://www.362tq.com/shunqing/zuotian.html 推荐查看天气:http://www.362tq.com/shunqing/7tian.html 推荐查看天气:http://www.362tq.com/shunqing/10tian.html 推荐查看天气:http://www.362tq.com/shunqing/15tian.html 推荐查看天气:http://www.362tq.com/shunqing/40tian.html 推荐查看天气:http://www.362tq.com/jialing/ 推荐查看天气:http://www.362tq.com/jialing/zuotian.html 推荐查看天气:http://www.362tq.com/jialing/7tian.html 推荐查看天气:http://www.362tq.com/jialing/10tian.html 推荐查看天气:http://www.362tq.com/jialing/15tian.html 推荐查看天气:http://www.362tq.com/jialing/40tian.html 推荐查看天气:http://www.362tq.com/nanbu/ 推荐查看天气:http://www.362tq.com/nanbu/zuotian.html 推荐查看天气:http://www.362tq.com/nanbu/7tian.html 推荐查看天气:http://www.362tq.com/nanbu/10tian.html 推荐查看天气:http://www.362tq.com/nanbu/15tian.html 推荐查看天气:http://www.362tq.com/nanbu/40tian.html 推荐查看天气:http://www.362tq.com/yingshan/ 推荐查看天气:http://www.362tq.com/yingshan/zuotian.html 推荐查看天气:http://www.362tq.com/yingshan/7tian.html 推荐查看天气:http://www.362tq.com/yingshan/10tian.html 推荐查看天气:http://www.362tq.com/yingshan/15tian.html 推荐查看天气:http://www.362tq.com/yingshan/40tian.html 推荐查看天气:http://www.362tq.com/pengan/ 推荐查看天气:http://www.362tq.com/pengan/zuotian.html 推荐查看天气:http://www.362tq.com/pengan/7tian.html 推荐查看天气:http://www.362tq.com/pengan/10tian.html 推荐查看天气:http://www.362tq.com/pengan/15tian.html 推荐查看天气:http://www.362tq.com/pengan/40tian.html 推荐查看天气:http://www.362tq.com/yilong/ 推荐查看天气:http://www.362tq.com/yilong/zuotian.html 推荐查看天气:http://www.362tq.com/yilong/7tian.html 推荐查看天气:http://www.362tq.com/yilong/10tian.html 推荐查看天气:http://www.362tq.com/yilong/15tian.html 推荐查看天气:http://www.362tq.com/yilong/40tian.html 推荐查看天气:http://www.362tq.com/xichong/ 推荐查看天气:http://www.362tq.com/xichong/zuotian.html 推荐查看天气:http://www.362tq.com/xichong/7tian.html