使用setTimeout推迟所有繁重的计算

时间:2014-12-01 01:43:46

标签: javascript asynchronous coffeescript underscore.js nonblocking

  1. 假设我有一个非常重的计算,它涉及两个嵌套的for循环遍历大小为1000 * 1000的数组

  2. 计算大约需要1分钟。

  3. 我在网页上还有很多其他内容,尤其是用户互动。 (点击,滚动,动画等)

  4. 现在我需要在某个时刻进行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?

1 个答案:

答案 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);