首页 > 解决方案 > 为什么 div 直到 for 循环完成才更新?

问题描述

在下面的 HTML 页面中,我希望在 for 循环运行时更新 div。但是,在循环结束之前没有发生 div 更新?

        <!DOCTYPE html>
        <html>
        <body>
        
        <h1>why div is not updated until the for loop is finished?</h1>
        
        
          <div id="myBar"></div>
        
        
        <br>
        <button onclick="afficheHeure()">Click Me</button> 
        
        <script>
        var p1 =  document.getElementById("myBar");
        function afficheHeure(){
            for(i=0; i< 50000; i++){
                setInterval(function(){
                    let d = new Date();
                    let e = d.getTime();
                    p1.innerHTML = e;
                }, 100);
                console.log("i vaut = " + i);
            }
        }
        
        </script>
        
        </body>
        </html>

标签: htmlloopsdisplay

解决方案


Javascript 函数是“原子的”,因为它们不会被“异步”函数中断。setInterval注册一个异步运行的函数。它一直等到没有其他函数在运行时才运行。

因为您正在向 注册函数setInterval,所以这些函数在间隔过去之前不会运行(并且当前没有其他 JS 函数正在运行)。然而,setInterval它本身是“非阻塞的”:它只是注册函数然后返回。这意味着它注册的功能尚未运行。

让我们看一下编写我们自己的“setDelayed”函数作为示例(它实际上不会等待特定的时间间隔,但它会让我们注册函数以便稍后运行):

const queue = []
function setDelayed (delayedFunction) {
  queue.push(delayedFunction)
}

function runDelayed () {
  console.info('running delayed functions')
  while (queue.length) queue.pop().call()
  console.info('done with delayed functions')
}

// now we put or code with the loop


 for(let i=0; i< 5; i++){
   setDelayed(function(){
     let e = new Date().getTime()
     console.log({e,i})
   })
   console.log("registered i value", i)
 }

// and now we manually trigger our delayed functions, like JS would normally do automatically
 runDelayed()

此外,如果您正在进行 DOM 更新(如您的示例),浏览器实际上会在呈现任何这些更改之前等待您的脚本完成。因此,如果您的循环需要足够长的时间,浏览器实际上会“冻结”,直到您的循环完成。有专门用于防止这种“冻结”的API 。


推荐阅读