DOM操作不会立即执行

时间:2015-06-09 13:51:16

标签: javascript dom race-condition

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

示例:



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

我希望看到一个进度条行为,而只有在他运行for循环时才会操纵DOM。

我尝试使用setTimeout进行异步方法但没有成功。

有没有很好的方法来实现这个目标?

3 个答案:

答案 0 :(得分:1)

使用类似的Javascript工具setTimeout,而不是使用循环和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作为示例。此代码可以使用更高的数字,但显示结果需要很长时间。

答案 1 :(得分:0)

将超时从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>

答案 2 :(得分:0)

由于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