setInterval 计时误差解决方案

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

下面给出解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 动态调整触发时间,减小误差耗时
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);