受限于js的单线程模式,使用定时器实现倒计时会出现一定程度的时间差,若存在比较耗时的其他任务的话,差值往往是不可接受的,一下分享一种使用setTimeout实现的倒计时效果,思路就是通过引入计数器,判断计时器延迟执行的时间来调整,尽量让误差缩小,不同浏览器不同时间段打开页面倒计时误差可控制在 1s 以内。
以下是代码实现:
// 开始线程占用
window.setInterval(function () {
var j = 0;
while(j++ < 100000000);
}, 0);
//倒计时
const interval = 1000;
var ms = 50000, // 倒计时时间差,这里测试用50000ms
count = 0,
startTime = new Date().getTime();
if (ms >= 0) {
var timeCounter = window.setTimeout(countDownStart, interval);
}
function countDownStart() {
count++;
var offset = new Date().getTime() - (startTime + count * interval);
var nextTime = interval - offset;
var daytohour = 0;
if (nextTime < 0) {
nextTime = 0
};
ms -= interval;
console.log("误差:" + offset + "ms,距离下一次执行:" + nextTime + "ms后,距离活动开始还有:" + ms + "ms");
if (ms < 0) {
window.clearTimeout(timeCounter);
} else {
timeCounter = window.setTimeout(countDownStart, nextTime);
}
}
由于线程阻塞延迟问题,做了 setTimeout 执行时间的误差修正,保证 setTimeout 执行时间一致。若冻结时间特别长的,可以在此基础上扩展处理