【问题标题】:Deferring all heavy computation using setTimeout使用 setTimeout 推迟所有繁重的计算
【发布时间】:2014-12-01 14:11:44
【问题描述】:
  1. 假设我有一个非常繁重的计算,它涉及两个嵌套的 for 循环,遍历大小为 1000*1000 的数组

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

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

  4. 现在我需要在某个时候进行 60 年代的计算。例如,我可以这样做:

    setTimeout TwoForLoops,0
    

    这将推迟函数调用,直到所有其他点击、滚动等事件都被清除。 但是,由于计算需要 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 毫秒,但 我不确定这是否可行。

    做什么?

【问题讨论】:

  • 您没有正确使用setTimeout。它接受一个函数作为它的第一个参数。
  • 是的,感谢您的快速更新

标签: javascript asynchronous coffeescript underscore.js nonblocking


【解决方案1】:

我认为您的代码将所有数百万个 HeavyComputation 可继续排队,而不是随着它的进展。事件循环会在处理新的用户事件之前按顺序处理每个事件,所以你仍然被阻塞了一分钟。

您应该使用 setImmediate,或者仔细检查 setTimeout of 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);

【讨论】:

  • 是的,我认为你说的很有道理。 Node.js/Chrome 会将所有百万计算完全放在事件循环中!并且用户事件将被放置在队列的最后
  • "注意:此方法预计不会成为标准,仅在 Internet Explorer 和 Node.js 0.10+ 的最新版本中实现。它遇到了 Gecko (Firefox) 和 Webkit (Google /苹果)。” developer.mozilla.org/en-US/docs/Web/API/Window.setImmediate "这个方法可以代替setTimeout(fn, 0)方法来执行繁重的操作。"
猜你喜欢
  • 1970-01-01
  • 2023-03-18
  • 1970-01-01
  • 1970-01-01
  • 2016-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-10
相关资源
最近更新 更多