关于倒计时实现

351 阅读2分钟

最近有在写一个移动端项目,验证码需要前端自己实现倒计时,刚好群友问到倒计时实现

群友的问题方案

let time = 0 
const start = () => {
    time = 60
    const flag = setInterval(()=>{
        time--
        if(time < 0 )clearInterval(flag)
    },1000)
}

const start2 = () => {
    time = 60
    run()
    function run(){
        time--
        if(time < 0){
            time = 0
        }else{
            setTimeout(run,1000)
        }
    }
}

逻辑十分的语义化

1. 开始设置时间为60
2. 每过1秒执行减1逻辑如果时间减少到0的时候结束

问题

1. 不管 setTimeout 还是 clearInterval 都不能保证刚好1秒之后立即执行,时间非准确的60秒误差不可控
2. 误执行会导致倒计时表现出错

我的方案

const minutes = 1000 * 60 // 一分钟
let oveTime = 0 // 倒计时结束时 间
let flag = null // timeout标记
let time = 0 // 倒计时结束时间
start()

funciton start(){
    oveTime = new Date() + minutes // 加法运算 时间戳 + 一分钟 = 结束时间
    run()
    function run (){
        const now = new Date()
        time = parseInt((oveTime - now) / 1000) // 结束时间 - 当前时间 的整数秒
        if(time < 0){ // 倒计时小于 0 秒 的时候暂停 
            time = 0
        }else{ // 倒计时大于等于0的时候 200 毫秒后继续轮询
            setTimeout(run, 200);
        }
    }
}

群友要求的内卷版本修复了上面的一些bug


    const minutes = 1000 * 60; // 一分钟
    let oveTime = 0; // 倒计时结束时 间
    let flag = null; // timeout标记
    let time = 0; // 倒计时结束时间
    start();

    function start() {
        oveTime = +new Date() + minutes; // 加法运算 时间戳 + 一分钟 = 结束时间
        run();

        function run() {
            const now = +new Date();
            time = parseInt((oveTime - now) / 1000); // 结束时间 - 当前时间 的整数秒
            console.log(time)
            if (time < 0) {
                // 倒计时小于 0 秒 的时候暂停
                time = 0;
            } else {
                // 倒计时大于等于0的时候 200 毫秒后继续轮询
                requestAnimationFrame(run);
            }
        }
    }