【问题标题】:How can I limit angular $q promise concurrency?如何限制角度 $q 承诺并发?
【发布时间】:2016-03-15 04:23:07
【问题描述】:

我该如何做类似$q.all 但限制并发执行的承诺数量?

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

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

另一个问题的公认答案是为promise 编写的库,包装后可与Q 一起使用。 但我对 Angular 的 $q 而不是 Q 的解决方案特别感兴趣。

背景:正在解决的问题:
我有一堆文件要分两步下载:a) 获取 URL b) 下载文件.
浏览器限制了可以同时检索的文件数量,因此当直接使用带有 $q.all 的 Promise 触发所有下载时,只有
N 立即发生,例如6 在 Chrome 中,而其余的则延迟。 (见Max parallel http connections in a browser?
问题是网址已经过期,所以当浏览器执行时 N+1th 文件下载,网址不再有效。
所以我想做throttled.all(6, promises)而不是$q.all(promise)

【问题讨论】:

    标签: angularjs concurrency promise angular-promise


    【解决方案1】:

    如果“所有”承诺的解决无关紧要(例如您正在更新页面上的某些元素,并且您不在乎它是否是渐进式的,而不是在一个“嗖嗖声”中),我创建了一个简单的任务队列服务。它不会等待所有 Promise 都被解决,而是会处理它获得的所有添加的 Promises/Functions/Tasks,并且最多处理。配置的限制值的并发性。

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

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

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

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

    如果任务返回一个返回一个承诺的承诺,依此类推,它将始终使用队列中的初始“槽”。因此,在整个 Task Promise 链被解决(或拒绝)后,它将为另一个添加的任务释放“槽”。

    【讨论】:

      【解决方案2】:

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

      这将允许您只使用$q。您只需要有一个您将使用的列表,$q.all 无论如何都需要它

      self.MakeCall = function(theList, chunkSize){
         //Split list into what will be processed and what should be held
          var processList = theList.slice(0,chunkSize);
          var holdList = theList.slice(chunkSize);
      
          return $q.all(processList).then(function(result) {
            //If holdList is empty you are finished
            if(holdList <= 0) {
              return result;
            }
            else {
              //More items make recursive call to process next set
              return self.MakeCall(holdList, chunkSize);
            }
          });
        };
      //Initialize Recursive call
      self.MakeCall(self.contacts);
      

      【讨论】:

      • 不错的开始,@Malkus,谢谢。它并不像我想象的那样并发,因为您的示例分成大小为 N 的块,而不是总是运行 N 个承诺......话虽如此,它肯定比顺序链更具并发性! :)
      【解决方案3】:

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

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

      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');
        });
      

      我选择了另一个答案。我认为这两个已经足够不同了,我不想对另一个进行更改

      【讨论】:

        【解决方案4】:

        我尝试了几种不同的方法来做到这一点,但最终决定为$q 编写一个扩展,以使用$q.allLimit() 扩展其$q.all 行为。

        请参阅angular-q-limit 模块了解更多详情。

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

        【讨论】:

        • 请详细说明它是如何工作的,而不是仅仅将链接粘贴到您的图书馆。
        • 这没有意义。 It's impossibleall 进行排序。
        • 道歉。我在这里添加了一些示例 - gist.github.com/hash-bang/652be06e3cf89f9d71fa2dfceb893719 - 如果您可以更具体地说明您要请求的内容,我可以写一些内容。
        • @bergi - 该模块的工作原理是创建一个包装承诺,然后执行承诺但保持在限制之下。它不会覆盖 $q.all() 而是提供一个元函数,该函数类似于将每个 Promise 包装在 .then() 序列链中。
        • promise 排序机制是如何实现的?只需edit 你的答案。 allLimit 实现的一些代码会很好。它不需要深入细节,但至少传达了大致的想法。
        猜你喜欢
        • 2015-01-15
        • 2015-11-24
        • 2019-10-17
        • 2013-12-31
        • 1970-01-01
        • 2015-02-25
        • 2015-05-12
        • 2016-07-07
        • 2016-05-18
        相关资源
        最近更新 更多