我以前也遇到过这样的问题。
编写代码时要记住的一点是,我的代码从哪里开始执行,以及我的代码在哪里结束执行。在这两点之间的所有时间里,浏览器的 UI 线程都被阻塞了,可以理解的是,浏览器制造商已经制定了应对措施。
至于要避免什么,请避免长而连续的循环。
这是一个极端的例子:
function howManyMultiplesOfFourBelow(foo) {
var i = 0, j = 0;
while (i < foo) {
i++;
if (i % 4 === 0) {
j++;
}
}
return j;
}
如果您将 10,000,000 传递给该函数,IE 肯定会出错。围绕这种情况进行编程的方法不止一种。我更喜欢使用setTimeout
/分解代码setInterval
。在设置一个时间间隔并返回一个函数后,我们将 UI 线程释放回浏览器,浏览器负责按照我们请求的频率(或尽可能频繁地)执行时间间隔。
我将它与Futures/Promises结合起来;特别是jQuery 的实现。使用这种风格,可以重写上面的例子,在计算过程中不阻塞 UI 线程,通过利用 Promise 和setInterval
.
function howManyMultiplesOfFourBelow(foo) {
var deferred = $.Deferred(),
interval,
i = 0,
j = 0;
interval = setInterval(function () {
if (i >= foo) {
clearInterval(interval);
deferred.resolve(j);
return;
}
i++;
if (i % 4 === 0) {
j++;
}
}, 1);
return deferred.promise();
}
第一个重要的区别是这个函数不再返回答案,而是一个答案的承诺。因此,使用代码可能如下所示:
howManyMultiplesOfFourBelow(10000000).done(function (multiples) {
//Update the DOM with the answer (multiples)
});
更一般地回到您的问题,考虑您的代码有多少必须连续运行,以及是否有任何代码可能被延迟或分解以短暂释放 UI 线程。