如何打破javascript中长期运行的功能,但保持性能 [英] How to break up a long running function in javascript, but keep performance

查看:32
本文介绍了如何打破javascript中长期运行的功能,但保持性能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的功能很长.它遍历一个大数组并在每个循环中执行一个功能.

I have a long running function. Which iterates through a large array and performs a function within each loop.

longFunction : function(){
       var self = this;
       var data = self.data;

       for(var i=0; len = data.length; i<len; i++){
              self.smallFunction(i);
       }
},
smallFunction : function(index){

// Do Stuff!

}

在大多数情况下,这很好,但是当我处理的数组大约在1500左右时,我们就可以收到javascript执行警告消息了.

For the most part this is fine but when I am dealing with arrays above around 1500 or so we get to the point of recieving a javascript execution alert message.

所以我需要分手.我的第一次尝试是这样的:

So I need to break this up. My first attempt is like so:

longFunction : function(index){
       var self = this;
       var data = self.data;


      self.smallFunction(index);

      if(data.slides[index+1){
         setTimeout(function(){
            self.longFunction(index+1);
         },0);
      }
      else {
               //WORK FINISHED
      }

},
smallFunction : function(index){

// Do Stuff!

}

所以在这里,我要删除循环,并引入一个自调用函数,该函数在每次迭代时都会增加其索引.为了将控制权返回给主UI线程以防止javascript执行警告方法,我添加了 setTimeout ,以使其在每次迭代后有时间进行更新.问题在于,使用这种方法完成实际工作需要的时间实际上要长10倍.似乎正在发生的是,尽管 setTimeout 设置为0,实际上它等待的时间更像是10毫秒.它在大型阵列上的建立速度非常快.删除 setTimeout 并让 longFunction 本身调用,可以提供与原始循环方法相当的性能.

So here I am removing the loop and introducing a self calling function which increases its index each iteration. To return control to the main UI thread in order to prevent the javascript execution warning method I have added a setTimeout to allow it time to update after each iteration. The problem is that with this method getting the actual work done takes quite literally 10 times longer. What appears to be happening is although the setTimeout is set to 0, it is actually waiting more like 10ms. which on large arrays builds up very quickly. Removing the setTimeout and letting longFunction call itself gives performance comparable to the original loop method.

我需要另一种解决方案,该解决方案的性能可与循环媲美,但不会引起javascript执行警告.不幸的是,在这种情况下不能使用webWorkers.

I need another solution, one which has comparable performance to the loop but which does not cause a javascript execution warning. Unfortunately webWorkers cannot be used in this instance.

请务必注意,在此过程中,我不需要完全响应的UI.刚好足以每隔几秒钟更新一次进度栏.

It is important to note that I do not need a fully responsive UI during this process. Just enough to update a progress bar every few seconds.

是否可以将其分解为大块的循环?IE.一次执行500次迭代,停止,超时,更新进度条,执行下500次等等.

Would breaking it up into chunks of loops be an option? I.e. perform 500 iterations at a time, stop, timeout, update progress bar, perform next 500 etc.. etc..

还有什么更好的吗?

答案:

唯一的解决方案似乎是将工作分块.

The only solution seems to be chunking the work.

通过将以下内容添加到自调用函数中,我允许UI每250次迭代更新一次:

By adding the following to my self calling function I am allowing the UI to update every 250 iterations:

 longFunction : function(index){
           var self = this;
           var data = self.data;


          self.smallFunction(index);

          var nextindex = i+1;

          if(data.slides[nextindex){
            if(nextindex % 250 === 0){
             setTimeout(function(){               
                self.longFunction(nextindex);
             },0);
            }
            else {
                self.longFunction(nextindex);
            }
          }
          else {
                   //WORK FINISHED
          }

    },
    smallFunction : function(index){

    // Do Stuff!

    }

我在这里所做的只是检查下一个索引是否可被250整除,如果是,则我们使用超时来允许主UI线程更新.如果没有,我们将直接再次致电.问题解决了!

All I am doing here is checking if the next index is divisble by 250, if it is then we use a timeout to allow the main UI thread to update. If not we call it again directly. Problem solved!

推荐答案

以下是我先前写的答案中修改的一些批处理代码:

Here's some batching code modified from an earlier answer I had written:

var n = 0,
    max = data.length;
    batch = 100;

(function nextBatch() {
    for (var i = 0; i < batch && n < max; ++i, ++n) {
        myFunc(n);
    }
    if (n < max) {
        setTimeout(nextBatch, 0);
    }
})();

这篇关于如何打破javascript中长期运行的功能,但保持性能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆