我的代码包含一个冗长的For
循环函数。接近循环的末尾是一个代码行,每次迭代时,都会增加用作状态栏的div
的宽度。问题?状态栏的宽度仅在其上方有alert
线时才会增加,以提醒我当前的循环计数器。当我评论alert
,网页冻结,我听到很多电脑呼呼,最终我得到一个A网页正在减慢你的浏览器。你想干什么?浏览器消息。功能概述如下:
function processData(dataArr) {
// initialize the status bar
var bar = document.createElement('div');
bar.setAttribute("style","top:7px;left:125px;height:25px;width:400px");
bar.id="StatusBar";
document.body.appendChild(bar);
// now start the loop:
for (var i=0;i<dataArr.length;i++) {
// do a lot of string manipulation and parsing on dataArr[i]
// update the status bar every 50 iterations
if (Math.ceil(i/50) == Math.floor(i/50)) {
alert('Loop # '+(i+1)); // If this line is commented out, the status bar stops updating!
}
bar.style.width = Math.round(((1+i)/dataArr.length)*400)+'px';
}
// loop has finished last iteration, remove status bar
document.body.removeChild(bar);
}
上面提到的alert
行是其存在使得代码正常运行(数据被处理,状态栏随循环计数器增长)或网页冻结和获取网页正在减慢浏览器警告之间的差异的行。任何人都可以解释为什么看似良性的alert
线会如此显着地改变这段代码的功能?
以下事实可能无关紧要,但万一它不是:在第二个函数中从onload: function()
的xmlhttpRequest
代码块中调用上述函数。
更新:我刚刚找到another possibly-related stackoverflow question,这表明可能的根本原因是这个函数是从onload
的xmlhttpRequest
块中调用的。然而,这个问题的答案并没有提供我的问题的解决方案,并且问题没有涉及相同的主题(我使用的是用户脚本,并且页面加载似乎不是问题,因为我能够生成初始状态栏没有任何困难。除了在每个循环结束时更新状态栏外,循环内没有进行网页操作。)
第二次更新:已更正,以便正确关闭括号
当在for
循环内时,一个看似无害的alert
的存在允许CSS
命令立即改变div
(div
更改命令紧跟循环内的alert
)每个循环增量,因为alert
命令调用事件循环等待用户的响应(例如,点击警告框上的OK
按钮)。在此等待期间,可以呈现DOM更改。如果没有alert
命令(或某些替代方法,例如定时器以显式地导致实时DOM更改呈现),则在所有Javascript函数完成并且代码的执行已返回到浏览器的主事件循环之前,不会在网页上呈现更改。在我的例子中,代码中的这一点是当函数返回到调用它的第二个函数时,在onload:
的xmlhttpRequest
块中。
这种行为的明确说明:虽然增加CSS
宽度的div
命令应该发生在每个for
循环增量的末尾,但是div
(用作状态栏)只是在每第50次循环迭代时生长,频率相同alert
编码执行。为了满足状态栏显示数据处理进度的需要,我在我的代码中重新构建了工作流程:在调用上述函数之前,我没有等到第二个函数的xmlhttpRequest
的所有数据块都被下载,我调用了上面的函数在下载时处理每个数据块。在xmlhttpRequest
块中运行良好的状态栏现在表示数据的组合下载和处理。