我怎样才能限制角度$ q承诺并发?

时间:2015-12-09 18:40:35

标签: angularjs concurrency promise angular-promise

我如何执行$q.all之类的操作但限制同时执行的承诺数量?

我的问题就像How can I limit Q promise concurrency?

  

我希望一次产生的进程不超过5个

另一个问题的接受答案是为promise编写的用Q编写的库。Max parallel http connections in a browser?。 但是我特别感兴趣的是Angular的$q而不是Q的解决方案。

背景:问题正在解决:
我有两个步骤下载的文件:a)获取URL b)下载文件。
浏览器限制了可以同时检索多少文件,因此当直接使用$q.all的承诺触发所有下载时,只有
N 立即发生,例如Chrome中有 6 ,其余则延迟。 (见release 3.12
问题是URL已过期,因此当浏览器执行 N + 1 th 文件下载时,该URL不再有效。
所以我想做一些像throttled.all(6, promises)而不是$q.all(promise)

的事情

4 个答案:

答案 0 :(得分:2)

如果“全部”Promises的解析无关紧要(就像你正在更新网页上的某些元素而你不关心它是否是渐进的而不是一个'嗖')我创建了一个简单的TaskQueue服务。它不会等待所有Promise被解决,而是会处理它获得的所有添加的Promises / Functions / Tasks以及最大值。配置的限制值的并发。

因为我只发现了这个和其他一些StackOverflows没有帮助解决我的问题。所以现在我想回馈社区。希望它对某人有所帮助。

它使用现代JS的东西,如const和lambda表达式,但如果你只是想要“旧”的东西,你可以简单地让它从像babel这样的预编译器编译下来。

https://gist.github.com/Blackskyliner/8b1bafed326044fa4f8b1ba2627d1117

它只是简单地处理其队列之后的任务,它们只是匿名函数,返回一个promise或值,被添加。它将遵循服务上可配置的“maxConcurrentTasks”变量。

如果Task返回一个返回promise的promise,那么它将始终使用队列中的初始'slot'。因此,在解决(或拒绝)整个任务承诺链之后,它将为其他添加的任务释放“插槽”。

答案 1 :(得分:0)

我认为你可以做一些递归的事情。

这样您就可以只使用lakeHdfsPath_。你只需拥有一个你将要使用的列表,无论如何你需要$q

$q.all

答案 2 :(得分:0)

这是一个运行并发Chunks的替代解决方案。它不像其他答案那么干净,但它更接近您所寻找的。

我留下了一些用于验证的标记。

self.list [...];

self.MakeCall = function(theList, chunkSize,methodTracker){
    //Set default chunkSize
    chunkSize = (chunkSize)?chunkSize:1;

    //Slice list using previously defined list 
    // so multiple instances can be runuse same list
    var processList = self.list.slice(0,chunkSize);
    self.list = self.list.slice(chunkSize);

    return $q.all(processList).then(function(result) {
      //If holdList is empty you are finished
      if(self.list <= 0) {
        console.debug("method last: " + methodTracker);
        return result;
      }
      else {
        //More items make recursive call to process next set
        console.debug("method: " + methodTracker);
        return self.MakeCall(self.list, chunkSize,methodTracker);
      }
    });
  };
  //Initialize Recursive call
  self.MakeCall(self.list,1,1).then(function() {
    console.warn('end 1');
  });
  //Initialize Second call that will run asynchronous with the first
  // this can be initialized as many times as you want concurrent threads
  self.MakeCall(self.list,1,2).then(function() {
    console.warn('end 2');
  });

我选择了另一个答案。我认为这两者是不同的,我不想改变其他

答案 3 :(得分:0)

我尝试了一些不同的方法来完成此操作,但最终决定编写$q的扩展程序,并使用$q.all扩展其$q.allLimit()行为。

有关详细信息,请参阅angular-q-limit模块。

该模块通过创建一个包装函数来工作,该函数接受一个Promises数组并按顺序执行它们(将并发执行限制为限制),直到所有这些都用完为止。然后它以与$q.all()相同的方式使用all的返回值来解析自己的promise。