为了避免独占浏览器的注意力,我们需要定期将控制权交给浏览器。
一种释放控制权的方法是使用setTimeout
,它可以安排一个“回调函数”在一段时间后被调用。例如:
var f1 = function() {
document.body.appendChild(document.createTextNode("Hello"));
setTimeout(f2, 1000);
};
var f2 = function() {
document.body.appendChild(document.createTextNode("World"));
};
在此处调用 f1
将向您的文档添加单词 hello
,安排一个挂起的计算任务,然后释放控制权给浏览器。最终,将调用 f2
。
请注意,仅仅 indiscriminately 使用 setTimeout
并不能像神奇的精灵尘一样轻松实现功能:您真正需要做的是将剩余的计算过程封装在回调函数中。通常,setTimeout
将成为函数中的最后一件事,而其他计算内容则被塞进回调函数中。
对于您的特定情况,代码需要被小心地转换为类似以下的形式:
var heavyWork = function(i, onSuccess) {
if (i < 300) {
var restOfComputation = function() {
return heavyWork(i+1, onSuccess);
}
return doSomethingHeavy(i, restOfComputation);
} else {
onSuccess();
}
};
var restOfComputation = function(i, callback) {
setTimeout(callback, 0);
};
在每个restOfComputation
上,它会将控制权释放给浏览器。
另一个具体的例子是: 如何排队播放一系列HTML5 <audio>声音片段?
高级JavaScript程序员需要知道如何进行这种程序转换,否则他们会遇到您遇到的问题。如果使用此技术,您会发现自己必须以奇怪的样式编写程序,其中每个可以释放控制的函数都接受回调函数。这种样式的技术术语称为“传递风格”或“异步风格”。
doSomethingHeavy
之间休眠一下。此外,如果这个函数涉及与某个服务器的通信,AJAX 可能是正确的选择。 - Eran Zimmerman GonendoSomethingHeavy
的调用设置一个setTimeout
。 - gen_Eric