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
我遇到过 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