您的当前位置:首页正文

setInterval倒计时以及解决倒计时误差

2024-11-19 来源:个人技术集锦
  • 出现误差的原因:

setInterval、setTimeout实现都会出现误差,这源于js的单线程。
他们的回调函数并不是到时后立即执行,而是等系统计算资源空闲下来后才会执行。
setInterval、setTimeout都属于宏任务

  • setInterval、setTimeout误差的不同之处

setInterval指定的是“开始执行”之间的间隔,并不考虑每次任务执行本身所消耗的时间。因此实际上,两次执行之间的间隔会小于指定的时间。比如,setInterval指定每 100ms 执行一次,每次执行需要 5ms,那么第一次执行结束后95毫秒,第二次执行就会开始。如果某次执行耗时特别长,比如需要105毫秒,那么它结束后,下一次执行就会立即开始。

为了确保两次执行之间有固定的间隔,可以不用setInterval,而是每次执行结束后,使用setTimeout指定下一次执行的具体时间。


let leftCount = (new Date('2023-12-31').getTime()-new Date().getTime())/1000; //倒计时剩余秒数

let timer = '';
let leftDays = '';
let leftHours = '';
let leftSecond = '';
let leftMinute = '';

function startMove(){
    timer = setInterval(()=>{
        leftCount-=1;
        leftSecond = Math.floor(leftCount%60);
        leftMinute = Math.floor(leftCount/60%60);
        leftHours = Math.floor(leftCount/60/60%24);
        leftDays = Math.floor(leftCount/60/60/24);
        console.log('剩余时间',leftDays+'天'+leftHours+'时'+leftMinute+'分'+leftSecond+'秒');
    },1000)

    if(leftCount<=0){
        clearInterval(timer)
    }
}
startMove(leftCount)


// 解决误差
const interval = 1000;
// 从服务器和活动开始时间计算出的时间差,这里测试用 50000 ms
let ms = 50000;
let count = 0;
const startTime = new Date().getTime();
let timeCounter;
if (ms >= 0) {
    timeCounter = setTimeout(countDownStart, interval);
}
function countDownStart() {
    count++;
    const offset = new Date().getTime() - (startTime + count * interval);
    let nextTime = interval - offset;
    if (nextTime < 0) {
        nextTime = 0;
    }
    ms -= interval;
    console.log(
        `误差:${offset} ms,下一次执行:${nextTime} ms 后,离活动开始还有:${ms} ms`
    );
    if (ms < 0) {
        clearTimeout(timeCounter);
    } else {
        timeCounter = setTimeout(countDownStart, nextTime);
    }
}

  • 检测误差demo
var start = new Date('2022-12-26').getTime();
var count = 0
let timer = setInterval(()=>{
    count += 1;
    console.log(new Date().getTime()-start);
    if(count===10){
        clearInterval(timer)
    }
},1000)

// 误差demo
var start = new Date().getTime(); // 1672012800000
var num = 0
let intimer = setInterval(()=>{
    num += 1;
    // 如何求误差
    // const offset = (new Date().getTime()-start)%1000
    console.log('误差:',(new Date().getTime()-start));
    console.log('误差:',new Date().getTime()-(start+1000*num));
    if(num===10){
        clearInterval(intimer)
    }
},1000)

显示全文