您在这里遇到的问题是您的所有函数都将使用last_refresh
. 当你定义一个函数时,它对范围内的变量有一个持久的引用,而不是创建它时它们的值的副本。更多:闭包并不复杂
你可以这样做:
function update() {
if (reg_index/reg_total>last_refresh)
document.getElementById("progress_line").style.width =" "+100*last_refresh+"px";
document.getElementById("progress_value").innerHTML=my_format(100*last_refreh,"###")+"%";
last_refresh+=0.01;
setTimeout(update, 0); // Or 5 or whatever
}
}
update();
它使用一个功能来完成一些工作,然后安排自己立即完成更多工作。它关闭了reg_index
、reg_total
和last_refresh
变量。
如果你知道它至少需要运行一次,你可以让它更高效一些:
function update() {
document.getElementById("progress_line").style.width =" "+100*last_refresh+"px";
document.getElementById("progress_value").innerHTML=my_format(100*last_refreh,"###")+"%";
last_refresh+=0.01;
if (reg_index/reg_total>last_refresh)
setTimeout(update, 0); // Or 5 or whatever
}
}
update();
为了帮助理解循环的概念setTimeout
,比较这个标准循环(浏览器直到最后才会更新):Live Copy | 直播源
var a = ["zero", "one", "two", "three", "four", "five"];
var index;
for (index = 0; index < a.length; ++index) {
display("Entry " + index + " is " + a[index]);
}
...使用这个等效的 using setTimeout
,它在每次迭代时都会让浏览器更新,因此它可以更新(即使间隔是0
,它的运行速度也会慢得多——我在200
这里使用过,所以你可以看到它运行):Live Copy | 直播源
var a = ["zero", "one", "two", "three", "four", "five"];
var index;
index = 0;
update();
function update() {
display("Entry " + index + " is " + a[index]);
++index;
if (index < a.length) {
setTimeout(update, 200);
}
}
下面你说:
不幸的是,我无法在我的示例中应用......我有一个在本地数据库上读取 2000 次的主循环......我已经使用超时完成了它,但现在我的代码花费了很多时间
我通常通过将事情分解成块来处理这个问题(或者参见下面的另一种选择),例如:Live Copy | 直播源
var index;
var total = 10000; // 10,000 to do in total
index = 0;
update();
function update() {
var limit = Math.min(index + 100, total); // Do them 100 at at time
while (index < limit) {
if (index % 10 == 0) {
display("Process entry #" + index);
}
++index;
}
if (limit < total) {
setTimeout(update, 200);
}
}
选择块的大小,这样您就可以足够频繁地更新(yield),但不要更新(yielding)太多以至于浪费太多时间。上面是根据循环的数量来做的,但另一种方法是让自己运行(比如说)一整秒然后屈服。你可以在一秒钟内完成很多工作。
另一种选择是使用网络工作者,至少在支持它们的浏览器上。我在 Stack Overflow 上的其他答案有一个讨论和示例。
但是,即使您使用网络工作者,您也可能希望将工作分成块,因为如果您有 2,000 条记录要通过,那么将进度条更新 2,000 次是没有意义的 &mdasdh; 您只需进行人类无法轻易感知的更新。100 次更新就足够了,甚至可能只有 20 条(因此,100 条记录/块)就可以了。