我在JS中执行长计算。在计算过程中,我想显示一个进度条,在每一步之后更新。为了正确触发DOM刷新,我使用setTimeout对步骤进行排队。我自己构建了一个这样的函数:
var sequence = function (ar, callback, finalCallback) {
if (ar && ar.length) {
setTimeout(function () {
callback && callback(ar.shift());
sequence(ar, callback, finalCallback);
}, 0);
} else {
finalCallback && finalCallback();
}
};
这几乎像预期的那样工作。我在回调中正确地执行了计算和DOM操作。唯一的问题是,所有的东西都非常慢。计算过程中CPU占用率仅为20%。
我的代码有什么问题吗?我想,所有的单步只是排队,由于超时0得到执行没有'真正的'暂停,但当浏览器没有什么可做的了。
编辑:我试图在Chrome和Firefox中执行,两者的行为方式相同。此外,我试图移动setTimeout之外的实际回调调用。这没什么区别。
根据建议,我尝试setInterval而不是settimeout,像这样:
var sequence = function (ar, callback, finalCallback) {
var interval = setInterval(function () {
if (ar && ar.length) {
callback && callback(ar.shift());
} else {
finalCallback && finalCallback();
clearInterval(interval);
}
}, 0);
};
它的行为与setTimeout版本完全相同。
这是小提琴,它显示的东西:
https://jsfiddle.net/by6oovhz/8/如果你删除setTimout,你会看到它实际上应该有多快(但DOM不再得到更新)。
我刚发现问题。setTimeout行为的原因是,这个方法总是有一个小的超时,即使你传递0作为参数。在这里,您可以阅读更多关于它的内容,并找到一个解决方法的链接。它使用窗口。postMessage创建一个函数,它的超时为0。
https://developer.mozilla.org/de/docs/Web/API/Window/setTimeout Minimum_delay_and_timeout_nesting
我认为你的函数已经触发了一大堆的超时对象到窗口。你可以试着这样修改你的函数,创建to,然后删除它。
myVar = setTimeout(function(){ mycallback }, 0); // id of timeout
和后面的代码中删除它
clearTimeout(myVar);
或者你可以尝试改变你的逻辑使用setInterval也许?
hth k