DOM 操作未立即执行

DOM Manipulation not executing instantly

我遇到过 DOM 操作仅在浏览器 运行 通过所有迭代时才生效的问题,即 while、for、-loops。

示例:

var text = document.getElementById("text");
for (var i = 0; i < 100000000; i++) {
  if (i % 1000000 == 0) {
    setTimeout(function() {
      text.innerHTML += "|";
    }, 0);
  }
}
<p id="text"></p>

我希望看到类似进度条的行为,相反 DOM 仅在他 运行 通过 for 循环时才被操纵。

我尝试了使用 setTimeout 的异步方法,但没有成功。

有什么好的方法可以实现吗?

将超时从 0 更改为 500,您将看到它的进展:

var text = document.getElementById("text");
for (var i = 0; i < 100000000; i++) {
  if (i % 1000000 == 0) {
    setTimeout(function() {
      text.innerHTML += "|";
    }, 500);
  }
}
<p id="text"></p>

但是,程序在进入空闲状态以处理第一个计时器之前必须完成计数到 1 亿。


这里有一个替代方法,不会占用太多计算机资源:

var text = document.getElementById("text");
for (var i = 0; i < 100; i++) {
  setTimeout(function() {
    text.innerHTML += "|";
  }, 10*i);
}
<p id="text"></p>

不要使用循环和 setTimeout,而是使用类似的 Javascript 工具 setInterval。这将 运行 每 N 毫秒重复一个函数。您可以使用计数器变量来跟踪何时添加进度条以及何时停止! http://jsfiddle.net/4odd386e/

var text = document.getElementById("text");
var i = 0;
function addOne() {
    i += 1;
    if (i % 10 === 0) {
        text.innerHTML += "|";
    }
    if (i === 1000) {
        // Progress complete
        clearInterval(initProgress);
    }
}
var initProgress = setInterval(addOne, 0);

此外,您最初使用的高数字导致进展非常缓慢,因此我以 10 和 1000 为例。此代码适用于更高的数字,但需要很长时间才能显示结果。

由于 Javascript 在单线程中运行,因此在完成计算处理之前一切都被阻塞。

为了进行非阻塞计算,您可以使用 webworkers 并在 worker 调度 postMessage 事件时更新 dom。

示例:

主要代码:

var text = document.getElementById("text");
var myWorker = new Worker("js/forloop.js");
myWorker.postMessage(2000);
myWorker.onmessage = function(e) {
   //e.data is an object which is passed from the worker
   if (e.data === true)
      text.innerHTML += "|";
}

WebWorker 代码:

onmessage = function(e) {
   for (var i = 0; i < e.data; i++) {
     postMessage(true);
   }
}

进一步阅读:Webworkers