最近做了一个小定时器的功能,但是在标签页切换后,定时器就会出现延迟。后面发现是在页面切换后,浏览器会自动延迟我们的定时器,以便于节约资源。
例子:开启一个定时器:0.5秒数字自增
大概6秒执行了14次
当前页
大概11秒执行14次
切换标签页
在我们切换标签页后,我们的定时器根据浏览器不同,已经能明显感觉到延迟了,这个时候如果我们要保持定时器精度,可以用web work来跑我们的代码,通过在worker里面开启定时器,发送message给外部,外部收到message,然后再执行操作,这样我们切换页面,但是worker不受影响,定时器就可以解决延迟了
// time worker
var intervalIds = {};
// 监听message 开始执行定时器或者销毁
self.onmessage = function(e){
switch(e.data.command){
case 'interval:start': // 开启定时器
var intervalId = setInterval(function(){
postMessage({
message: 'interval:tick',
id: e.data.id
})
},e.data.interval);
postMessage({
message: 'interval:started',
id: e.data.id
});
intervalIds[e.data.id] = intervalId;
break;
case 'interval:clear': // 销毁
clearInterval(intervalIds[e.data.id]);
postMessage({
message: 'interval:cleared',
id: e.data.id
})
delete intervalIds[e.data.id];
break;
}
}
开启worker
var worker = new Worker('./time-worker.js');
var workerTimer = {
id: 0,
callbacks: {},
setInterval: function(cb, interval, context) {
this.id++;
var id = this.id;
this.callbacks[id] = { fn: cb, context: context };
worker.postMessage({ command: 'interval:start', interval: interval, id: id });
return id;
},
// 监听worker 里面的定时器发送的message 然后执行回调函数
onMessage: function(e) {
switch (e.data.message) {
case 'interval:tick':
var callback = this.callbacks[e.data.id];
if (callback && callback.fn) callback.fn.apply(callback.context);
break;
case 'interval:cleared':
delete this.callbacks[e.data.id];
break;
}
},
// 往worker里面发送销毁指令
clearInterval: function(id) {
worker.postMessage({ command: 'interval:clear', id: id });
}
};
worker.onmessage = workerTimer.onMessage.bind(workerTimer);
然后我们使用的时候,直接用worker.setInterval或者workerTimer.clearInterval就可以了

如果需要加入setTimeout,也是一样的步骤
网友评论