在尝试回答this question时,我遇到了一种奇怪的行为(这是不一样的:他的迭代次数太少,我的太多了):
HTML:
<button id="go">it will be legend...</button>
<div id="output"></div>
JS:
var output = document.getElementById('output');
document.getElementById('go').onclick = function() {
output.textContent += 'wait for it...';
for (var i=0; i<3000000000; i++) {
var unused = i; // don't really care
}
output.textContent += ' dary!';
};
循环需要几秒钟才能执行,因为它有3,000,000,000次迭代。
点击按钮后,我的期望是:
wait for it...
出现dary!
出现实际发生了什么:
wait for it... dary!
一起出现 知道为什么会出现这种行为吗?
自己检查:fiddle。
答案 0 :(得分:17)
原因是函数整体上是同步执行的。当您将输出设置为wait for it...
时,它将进入长时间运行的循环并占用线程。如果将其余部分包裹在timeout
中,则第一个文本将显示为正常。
var output = document.getElementById('output');
document.getElementById('go').onclick = function() {
output.textContent += 'wait for it...';
window.setTimeout(function() {
for (var i=0; i<3000000000; i++) {
var unused = i; // don't really care
}
output.textContent += ' dary!';
}, 0);
};
请注意,处理时仍会冻结用户界面。
修改:使用0
作为Chrome中的延迟值,但最新的Firefox和IE 10中没有。在两种情况下都将值更改为10
答案 1 :(得分:10)
Javascript几乎是单线程的。如果您正在运行代码,则该页面无响应,并且在您的代码完成之前不会更新。 (请注意,这是特定于实现的,但这就是今天所有浏览器都这样做的。)
答案 2 :(得分:2)
根据this SO post by user Cocco,为此目的,setTimeout
使用requestAnimationFrame
的效果不如$(document).ready(function() {
var W = window,
D = W.document,
i = 0,
x = 0,
output = D.getElementById('output');
function b() {
if (x == 0) {
output.textContent = 'wait for it...';
x++;
}
i++;
if (i < 300) {
//if (i > 20) output.textContent = i;
requestAnimationFrame(b);
} else {
D.body.style.cursor = 'default';
output.textContent += ' dary!';
}
}
function start() {
console.log(D)
D.body.style.cursor = 'wait';
b();
}
D.getElementById('go').onclick = start;
}); //END $(document).ready()
。那么,这是如何使用requestAnimationFrame:
{{1}}
注意:为了表示同意/赞赏,请在上面的帖子中提升Cocco's answer而不是这个。谢谢。
答案 3 :(得分:1)
您的代码正在按预期执行。问题是浏览器不会在javascript完成之后显示对文档的更改。超时是通过将代码执行分解为两个单独的事件来解决此问题。以下代码将显示您的预期正在发生。
var output = document.getElementById('output');
document.getElementById('go').onclick = function() {
console.log('wait for it...';)
for (var i=0; i<3000000000; i++) {
var unused = i; // don't really care
}
console.log(' dary!');
};
使用超时解决方案时也需要小心,因为执行不再是同步的。
output = document.getElementById('output');
document.getElementById('go').onclick = function() {
output.textContent += 'wait for it...';
window.setTimeout(function() {
for (var i = 0; i < 3000000000; i++) {
var unused = i;
// don't really care
}
output.textContent += ' dary!';
}, 0);
output.textContent += ' epic';
};
如果您运行此版本,您会注意到'epic'在'dary'之前。
答案 4 :(得分:0)
我看到的唯一解释是浏览器在执行javascript后刷新视图?作为证据,这可以按预期工作:
var output = document.getElementById('output');
document.getElementById('go').onclick = function () {
output.textContent += 'wait for it...';
window.setTimeout(count, 100);
};
function count() {
for (var i = 0; i < 3000000000; i++) {
var unused = i; // don't really care
}
output.textContent += ' dary!';
}