setInterval计时器不准的问题解决方法

setInterval计时器不准的问题解决方法

在js中如果打算使用setInterval进行倒数,计时等功能,往往是不准确的,针对这个问题,本文有个不错的解决方案
在js中如果打算使用setInterval进行倒数,计时等功能,往往是不准确的,因为setInterval的回调函数并不是到时后立即执行,而是等系统计算资源空闲下来后才会执行.而下一次触发时间则是在setInterval回调函数执行完毕之后才开始计时,所以如果setInterval内执行的计算过于耗时,或者有其他耗时任务在执行,setInterval的计时会越来越不准,延迟很厉害. 

下面的代码可以说明这个问题 
复制代码代码如下:

var startTime = new Date().getTime(); 
var count = 0; 
//耗时任务 
setInterval(function(){ 
var i = 0; 
while(i++ < 100000000); 
}, 0); 
setInterval(function(){ 
count++; 
console.log(new Date().getTime() - (startTime + count * 1000)); 
}, 1000); 

代码里输出了setInterval触发时间和应该正确触发时间的延迟毫秒数 
复制代码代码如下:

176 
340 
495 
652 
807 
961 
1114 
1268 
1425 
1579 
1734 
1888 
2048 
2201 
2357 
2521 
2679 
2834 
2996 
...... 

可以看到延迟是越来越严重的. 

为了在js里可以使用相对准确的计时功能,我们可以 
复制代码代码如下:

var startTime = new Date().getTime(); 
var count = 0; 
setInterval(function(){ 
var i = 0; 
while(i++ < 100000000); 
}, 0); 
function fixed() { 
count++; 
var offset = new Date().getTime() - (startTime + count * 1000); 
var nextTime = 1000 - offset; 
if (nextTime < 0) nextTime = 0; 
setTimeout(fixed, nextTime); 

console.log(new Date().getTime() - (startTime + count * 1000)); 

setTimeout(fixed, 1000); 

代码里,通过1000(也就是周期时间)减去当前时间和准确时间的差距,来算出下次触发的时间,从而修正了当前触发的延迟. 

下面是输出 
复制代码代码如下:

186 
200 
230 
271 
158 
899 
900 
899 
900 
899 
899 
899 
902 
899 
418 
202 
232 
266 
145 
174 
192 
214 
242 
268 
149 
179 
214 
...... 

可以看到虽然触发时间并非绝对准确,但由于每次触发都进行及时修正,所以并没有造成误差积累.

你可能感兴趣的:(js,性能优化)