最近做了一个小定时器的功能,但是在标签页切换后,定时器就会出现延迟。后面发现是在页面切换后,浏览器会自动延迟我们的定时器,以便于节约资源。
例子:开启一个定时器:0.5秒数字自增
大概6秒执行了14次
当前页
大概11秒执行14次
切换标签页
在我们切换标签页后,我们的定时器根据浏览器不同,已经能明显感觉到延迟了,这个时候如果我们要保持定时器精度,可以用web work来跑我们的代码,通过在worker里面开启定时器,发送message给外部,外部收到message,然后再执行操作,这样我们切换页面,但是worker不受影响,定时器就可以解决延迟了
// time workervar 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就可以了
使用web worker 延迟问题就解决了
如果需要加入setTimeout,也是一样的步骤
作者:Tiny_z
链接:https://www.jianshu.com/p/3571ca7e0573