定时器(如 setTimeout
和 setInterval
)是前端开发中常用的工具,它们允许我们在设定的时间后执行代码。但是,笔者最近遇到了一个共同的问题:当页面变为后台运行的时候,定时器会突然不准确,不足一分钟的定时器会变为定时一分钟左右。这篇文章将深入探讨背后的原因,并提供一些解决方案。
现代浏览器非常注重性能和能源效率,尤其是当涉及到后台标签页或者非激活窗口的时候。为了减少计算资源的使用,节省电池寿命,浏览器实施了一些限制措施,其中之一就是降低后台页面的定时器精度。
当你的页面转入后台运行后,浏览器可能会:
例如,Chrome 浏览器在后台标签的 setTimeout
/setInterval
函数调用中,会将最小延迟时间设置为1分钟。这意味着无论你将延迟时间设为多少,定时器实际执行的间隔都将不会小于 1 分钟。
对于需要精准定时的情况,比如游戏、动画,或某些实时同步应用,这会造成大问题。用户在将页面切换到后台之后,再次返回时,会发现计时器显示异常,或者定时触发的动作延迟执行。
Web Workers
Web Workers 在大多数的浏览器中运行在后台线程,不受前台 UI 渲染的干扰。使用 Web Workers 可以让定时器任务在后台精准运行。
WebRTC 或 WebSockets
如果你在开发实时通信应用,可以使用 WebRTC 或 WebSockets,这些技术专为实时通信设计,提供更稳定的连接和定时,即使在后台也能保持连接。
Service Workers
Service Workers 运行于浏览器后台,可以用作执行消息推送和后台同步任务,但并不适合周期性的短时定时任务。
请求动画帧 (requestAnimationFrame
)
对于动画,requestAnimationFrame
是更佳的选择。它会在浏览器准备好进行下次重绘时调用函数,因此在标签页处于非激活状态时将不会执行,这符合我们对于动画的需求。
Alarm API (实验性 API)
移动平台上,Web 应用可以尝试使用 Alarm API 定时执行事件,但需要注意这是一个实验性 API。
Chrome唤醒定时器API (实验性 API)
Chrome 考虑到了后台定时器的必要性,因此在其实验性定时器API中提供了唤醒定时器的能力,但它仍然是实验性的。
当页面进入后台,浏览器出于性能和能效考虑限制定时器的运行。开发者可以通过选择正确的工具和技术来设计更加健壮和用户友好的应用。在编写对时间敏感的应用时,开发者需要仔细考虑和测试其在各种环境下的运行情况。