我的问题更复杂,但我已经达到了这个简单的问题。简洁的例子:
HTML:
First: <span id="first"></span> <br/>
Then: <span id="second"></span> <br/>
And then: <span id="third"></span> <br/>
And then: <span id="fourth"></span> <br/>
And then: <span id="fifth"></span>
JS(+ jQuery(如果有关系)):
$(document).ready(function() {
doStuff();
});
function doStuff() {
$("#first").text(new Date().getSeconds());
var i = 1;
while (i < 1000000000) {
i++;
}
$("#second").text(new Date().getSeconds());
var i = 1;
while (i < 1000000000) {
i++;
}
$("#third").text(new Date().getSeconds());
var i = 1;
while (i < 1000000000) {
i++;
}
$("#fourth").text(new Date().getSeconds());
var i = 1;
while (i < 1000000000) {
i++;
}
$("#fifth").text(new Date().getSeconds());
}
从这个例子中,我的直觉告诉我$("#first")
应该在$("#fifth")
之前接收文本值。但是,它们都出现在同一时间。不,这不是JS运行得非常快的问题,正如您在示例中看到的那样$("#first")
的值比$("#fifth")
低约2秒。
为什么会发生这种情况(以及什么!),以及存在哪些解决方案?
答案 0 :(得分:0)
javascript阻止页面呈现,因此在完成所有javascript块之前,它不会呈现html输出。
答案 1 :(得分:0)
JavaScript在完成之前阻止UI。它应该是一种单线程语言,但是(如this post中所述)并不那么简单。
问题的解决方案是使用setTimeout
。请参阅updated simplified fiddle(该示例不适用于复制粘贴,但我相信它足以提出这个想法):
$(document).ready(function() {
doStuff();
});
function doStuff() {
$("#first").text(new Date().getSeconds());
var i = 1;
setTimeout(function() {
while (i < 1000000000) {
i++;
}
$("#second").text(new Date().getSeconds());
}, 0);
}
setTimeout
确保doStuff
函数完成,然后浏览器处理DOM更改,然后执行另一个函数(传递给setTimeout
方法)。
可以找到关于为什么事情以这种方式发生的简明扼要的解释here(感谢@bhspencer提供链接)。简单地说:JS在处理doStuff
方法时,UI被阻止(由于其单线程性质)。对第二个参数设置为0毫秒的setTimeout
的调用将(立即)放入处理队列中的另一段代码(setTimeout
的第一个参数)。然后doStuff
方法完成。 JS然后处理队列中的下一个项目 - 显然是UI更新。同样,当UI更新完成后,队列中的下一个项目就是setTimout
调用添加的内容。