如何在 JS 循环中更新 HTML UI

How to update HTML UI while in a JS loop

提问人:Gerald Negvesky 提问时间:5/4/2023 最后编辑:Christoph RackwitzGerald Negvesky 更新时间:5/5/2023 访问量:71

问:

在这里,我尝试根据循环的进度更新进度条,但是在嵌套循环通过之前,进度条不会更新,这并不理想。

function upload_img() {
    // Actual progress bar
    progress_bar = document.querySelector("#progress-bar");
    document.querySelector("#bar-area").style.display = "flex";

    //**Omitted

    setTimeout(function() {
        //**Omitted

        let size = obj_data.length * obj_data[0].length;

        for (let row = 0; row < obj_data.length; row++) {
            for (let col = 0; col < obj_data[0].length; col++) {
                // Incrementing counter
                j++;

                if (j % 1000 === 0 || j === size) {
                    //Should be updating progress bar every 1000 out of 13400, but is not doing so until end^^^^
                    progress_bar.style.width = `${Math.round(j / size * 100)}%`;
                    console.log(`${j} of ${size} so percent is ${j / size * 100}`)
                }

                   
            }

        }

    }, 1)

}

我尝试使用间隔/超时,但它们没有帮助。

JavaScript HTML 循环用户界面

评论


答:

1赞 Thomas Frank 5/4/2023 #1

我经常发现使用 async/await 比使用 setTimeout/setInterval 等更容易。然后,你所要做的就是在每次循环迭代之间休眠/等待/暂停数毫秒(这让浏览器有时间重新呈现屏幕,因为如果你不暂停脚本,它就不会这样做)。

要是 JavaScript 有睡眠功能就好了......实际上,你可以用一行代码编写一个睡眠函数:接收一些毫秒,创建一个将在该毫秒数后解析的承诺,并在此函数中使用一次 setTimeout 来实现这一点。

由于使用 await 是等待 promise 解析,因此您可以在循环中执行 await sleep(ms)(只要它在异步函数中 - 允许 await 的函数)。

下面进度条的实现基于这个想法,允许您根据需要更新循环中的进度条。

当然,您可以在该循环中执行其他操作(或调用执行其他操作的函数) - 例如上传内容,获取内容等。但是在这个例子中,我专注于进度条,你可以在循环中更新它。

async function progressBarExample() {
  const sleep = ms => new Promise(res => setTimeout(res, ms));
  const pBarEl = document.querySelector('.progress-bar div');
  const pBarTextEl = document.querySelector('.progress-bar span');
  const loopMax = 1000;
  for (let i = 0; i < loopMax; i++) {
    let percent = (i / loopMax) * 100;
    pBarEl.style.width = percent + '%';
    pBarTextEl.innerText = Math.round(percent) + '%';
    await sleep(20);
  }
}

progressBarExample();
.progress-bar {
  border-radius: 5px;
  width: calc(100% - 40px);
  margin: 20px;
  background-color: #999;
  height: 30px;
  position: relative;
}

.progress-bar div {
  border-radius: 5px;
  background-color: #1f1f85;
  height: 30px;
  width: 0%;
}

.progress-bar span {
  position: absolute;
  top: 0;
  left: 0;
  display: block;
  width: 100%;
  text-align: center;
  color: #fff;
  margin-top: 5px;
  font-family: Verdana;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Progressbar</title>
</head>

<body>
  <div class="progress-bar">
    <div></div>
    <span></span>
  </div>
</body>

</html>