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

  • 出现误差的原因:

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)

在这里插入图片描述
可以从图中明显的看出打印的结果,大多数时间每次相差结果不等于1000,因此使用setInterval长期下去,误差会很大。为解决这个问题,

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值