介绍
作为日常开发中经常使用到的方法,本文将主要探讨JS定时器中的setInterval和setTimeout在浏览器可见和不可见状态下的表现,以及提供一种解决定时器间隔时间误差的方案。

浏览器可见和不可见状态
首先需要知道,浏览器的可见和不可见状态的切换会触发visibilitychange事件,通过监听这个事件可以判断浏览器当前的可见状态。document.visibilityState有三个值:hidden、visible和prerender,其中hidden表示页面彻底不可见,visible表示页面至少一部分可见,prerender表示页面正在或即将渲染,但处于不可见状态。关键词:document.hidden 返回布尔值,为true表示当前浏览器是不可见状态。
setInterval和setTimeout在不可见状态下的表现
setInterval:在谷歌和火狐浏览器中,当页面处于不可见状态时,setInterval的最小间隔时间会被限制为1s;但是ie浏览器没有对不可见状态时的setInterval进行性能优化,不可见前后间隔时间不变。
setTimeout:在谷歌浏览器中,当间隔低于1s时会变为1s,大于等于1s的会变成N + 1s的间隔值;而在火狐浏览器中,间隔时间低于1s会变为1s,大于等于1s的间隔不变;与此不同的是,ie浏览器在不可见状态前后间隔时间不变。
requestAnimationFrame在不可见状态下的表现
requestAnimationFrame是处理动画效果的一种优化方法,普通显示器的刷新率是60hz,因此它在一秒之内需要运行60次,间隔时间大概是17ms。在谷歌和ie浏览器中,当浏览器状态为不可见时,raf方法将停止执行;而在火狐浏览器中,会在间隔是1s、2s、4s、8s、16s、32s这样的顺序下去执行raf方法。
解决方案
对于定时器间隔时间误差较大的问题,可以使用webWorkers来解决。示例代码如下:
<script>
document.getElementById('btn').addEventListener('click', function() {
var w = new Worker('demo_workers.js');
w.onmessage = function(event) {
console.log(event.data);
};
});
document.addEventListener('visibilitychange', function() {
if (document.hidden) {
console.log('页面不可见');
}
});
</script>
//demo_workers.js
setInterval(function() {
const myDate = new Date();
const currentDate = myDate.getMinutes() + '分' + myDate.getSeconds() + '秒' + myDate.getMilliseconds() + '豪秒';
postMessage(currentDate);
}, 500);
通过这种方式,可以解决在一些定时器小于1s的倒计时页面中,用户切换到其他标签页再切回时页面上显示的倒计时时间错误的问题,同时也可以解决页面存在多个定时器时间隔时间误差较大的问题。
原创文章,作者:小编小本本,如若转载,请注明出处:https://www.benjiyun.com/yunzhujiyunwei/vps-yunwei/7292.html
