为什么在Javascript中计数器动画中使用setTimeout?

为什么在Javascript中计数器动画中使用setTimeout?,javascript,Javascript,我试图找到这个问题的答案,但在任何地方都找不到 这里是我的动画代码: let counters = document.querySelectorAll('.counter'); counters.forEach(counter => { counter.innerText = 0; let target = +counter.dataset.count; let step = 1; let countIt = function (

我试图找到这个问题的答案,但在任何地方都找不到

这里是我的动画代码:

let counters = document.querySelectorAll('.counter');

   counters.forEach(counter => {
       counter.innerText = 0;
       let target = +counter.dataset.count;
       let step = 1;

    let countIt = function () {
        let displayedCount = +counter.innerText; // 0
        if(displayedCount < target) {
            counter.innerText = displayedCount + step;

            setTimeout(countIt, 1);

            // countIt(); // here if i call countIt directly then my counter animation does not work. 
                          //but with setTimeout it works.
        } else {
            counter.innerText = target;
        }

    }
    countIt();

   })
let counters=document.querySelectorAll('.counter');
counters.forEach(计数器=>{
counter.innerText=0;
让target=+counter.dataset.count;
设阶跃=1;
设countIt=函数(){
let displayedCount=+counter.innerText;//0
如果(显示计数<目标){
counter.innerText=displayedCount+step;
设置超时(countIt,1);
//countIt();//这里如果我直接调用countIt,那么我的计数器动画将无法工作。
//但是使用setTimeout它可以工作。
}否则{
counter.innerText=目标;
}
}
countIt();
})

所以我的问题是为什么会发生这种情况?任何人都可以向我解释引擎盖下发生了什么?

当JavaScript代码在主JavaScript线程上运行时,浏览器不会重新绘制页面。只需直接调用
countIt
,您就可以在同一个JavaScript作业中完成所有更新,然后浏览器在完成后重新绘制页面。通过使用
setTimeout
,您可以将更新分为多个JavaScript作业,这些作业的间隔约为1ms,因此浏览器有机会在它们之间重新绘制

您可以在和JavaScript规范的部分中找到详细信息。它们使用的术语略有不同:JavaScript“脚本作业”主要是HTML“任务”,JavaScript“承诺作业”是HTML“微任务”的一种


您可能还对它感兴趣,它提供了一种在重新绘制页面之前请求回调的方法。现在,您的计数器在重新绘制之间更新多次,通常每16.667ms更新一次。因此,浏览器不会绘制您在计数器DOM元素中输入的所有值。

当JavaScript代码在主JavaScript线程上运行时,浏览器不会重新绘制页面。只需直接调用
countIt
,您就可以在同一个JavaScript作业中完成所有更新,然后浏览器在完成后重新绘制页面。通过使用
setTimeout
,您可以将更新分为多个JavaScript作业,这些作业的间隔约为1ms,因此浏览器有机会在它们之间重新绘制

您可以在和JavaScript规范的部分中找到详细信息。它们使用的术语略有不同:JavaScript“脚本作业”主要是HTML“任务”,JavaScript“承诺作业”是HTML“微任务”的一种


您可能还对它感兴趣,它提供了一种在重新绘制页面之前请求回调的方法。现在,您的计数器在重新绘制之间更新多次,通常每16.667ms更新一次。因此,浏览器不会绘制您在计数器DOM元素中输入的所有值。

谢谢您的回答。我在读关于setTimeout的书。他们说setTimeout将只在所有js代码执行后运行。因此,在这种情况下,它是否正在等待运行整个循环和递归,并且当主代码完成时,只有setTimeout代码运行?@TrueCode-forEach循环运行到完成。每个
forEach
回调中的代码安排一个计时器回调。当每个回调都运行时,它会安排另一个回调。等等,直到你到达目标。很抱歉,
安排一次计时器回调是什么意思。
?@TrueCode-这就是
setTimeout
的作用。调用
setTimeout
时,要求浏览器在给定的毫秒数过后调用传入的函数。对函数的调用是来自计时器的回调。好的,我知道了。你是说超时。所以当forEach完成时,所有计划的计时器都在运行。它以1毫秒的间隔运行这就是为什么它有时间在1毫秒内重新绘制浏览器?我的理解正确吗?)谢谢你的回答。我在读关于setTimeout的书。他们说setTimeout将只在所有js代码执行后运行。因此,在这种情况下,它是否正在等待运行整个循环和递归,并且当主代码完成时,只有setTimeout代码运行?@TrueCode-forEach循环运行到完成。每个
forEach
回调中的代码安排一个计时器回调。当每个回调都运行时,它会安排另一个回调。等等,直到你到达目标。很抱歉,
安排一次计时器回调是什么意思。
?@TrueCode-这就是
setTimeout
的作用。调用
setTimeout
时,要求浏览器在给定的毫秒数过后调用传入的函数。对函数的调用是来自计时器的回调。好的,我知道了。你是说超时。所以当forEach完成时,所有计划的计时器都在运行。它以1毫秒的间隔运行这就是为什么它有时间在1毫秒内重新绘制浏览器?我的理解正确吗?)