假设我有一个非常重的计算,它涉及两个嵌套的for循环遍历大小为1000 * 1000的数组
计算大约需要1分钟。
我在网页上还有很多其他内容,尤其是用户互动。 (点击,滚动,动画等)
现在我需要在某个时刻进行60秒计算。我可以这样做:
setTimeout TwoForLoops,0
这会将函数调用推迟到所有其他on-click,on-scroll等事件被清除。 但是,由于计算需要1分钟,因此用户可能会在此期间触发某些事件。 你认为如果我只是做以下我会阻止JavaScript挂起。假设重计算 计算需要大约0.06毫秒。
# _.map is from underscore@ library, basically does a for loop
# HeavyComputation is a slow function with lots of operations made for my app
NonBlockMap = (x,f)-> setTimeout (->_.map x,f),0
NonBlockHeavyComputation = (x) -> setTimeout (-> HeavyComputation(x)),0
TwoForLoops = (ArrayOfArray) ->
SecondLoop = (element) -> NonBlockHeavyComputation element
FirstLoop = (array) -> NonBlockMap array, SecondLoop
return NonBlockMap ArrayOfArray,FirstLoop
这实际上意味着最大的javascript将挂起约为0.06毫秒但是 我不确定这是否有用。
WhatDo?
答案 0 :(得分:0)
我认为你的代码会预先排队所有百万个HeavyComputation的可持续性,而不是它的进展。在处理新的用户事件之前,事件循环将按顺序处理每个事件,因此您仍然会被阻止一分钟。
你应该使用setImmediate,或者仔细检查setTimeout为0是否没有睡眠。 Nodejs(我工作的东西;也许是chrome?)总是睡1毫秒。
考虑批量计算嵌套循环,例如:
function batchedHeavyComputation( elements, iFrom, jFrom, batchSize ) {
var i, j, numcalls = 0;
for (i=iFrom; i<1000; i++) {
for (j=jFrom; j<1000; j++) {
HeavyComputation(elements[i][j])
if (++numcalls >= batchSize) {
setImmediate(function(){
var jNext = j < 999 : j+1 : 0;
var iNext = j < 999 ? i : i+1;
batchedHeavyComputation(elements, iNext, jNext, batchSize);
});
return;
}
}
}
}
batchedHeavyComputation(elements, 0, 0, 20);