SOURCE

function example1(leftTime) {
    let t = leftTime;
    setInterval(() => {
        t = t - 1000;
        console.log(t);
    }, 1000);
}
// setInterval 因网络延迟、服务器无响应等问题,
// js 因为是单线程的原因,如果前面有阻塞线程的任务,那么就可能会导致 setInterval 函数延迟
//example2(10000);

// setTimeout 会在后台一直运行
function example2(leftTime) {
    let t = leftTime;
    setTimeout(() => {
        t = t - 1000;
        if (t > 0) {
            console.log(t);
            example2(t);
        }
        console.log(t);
    }, 1000);
}

// requestAnimationFrame
// 浏览器 API,允许以 60 帧/秒 (FPS) 的速率请求回调,而不会阻塞主线程。通过调用 requestAnimationFrame 方法浏览器会在下一次重绘之前执行指定的函数

//  requestAnimationFrame + setTimeout呢?
// 一个是息屏或者切后台的操作时,requestAnimationFrame 是不会继续调用函数的,
// 但是如果只使用requestAnimationFrame 的话,函数相当于 1 秒的时候要调用 60 次,太浪费性能。
//example4(9000)
function example4(leftTime) {
    let t = leftTime;
    function start() {
        requestAnimationFrame(() => {
            t = t - 1000;
            setTimeout(() => {
                console.log(t);
                start();
            }, 1000);
        });
    }
    start();
}

//
example5(9000)
function example5(leftTime) {
    const now = performance.now();
    function start() {
        setTimeout(() => {
            const diff = leftTime - (performance.now() - now);
            console.log(diff);
            requestAnimationFrame(start);
        }, 1000);
    }
    start();
}
console 命令行工具 X clear

                    
>
console