限制Q在Node js中承诺并发

有没有办法限制在js节点上同时执行的并发Q promise的数量?

我正在构建一个网页报废器,它必须请求并解析更多3000多页,并且不会扼杀我所做的某些请求没有及时响应,因此连接停止,并且所需的响应(html代码)不可用。

为了反击这一点,我发现限制了我的问题消失的请求数量。


我尝试了以下方法,但无济于事:

  • Q承诺中的并发限制 - 节点
  • 我怎样才能限制Q promise的并发性?
  • https://gist.github.com/gaearon/7930162
  • https://github.com/ForbesLindesay/throat
  • 我需要请求一个url数组,每次只做一个请求,当数组中的所有url都完成时,然后将结果返回到数组中。

    function processWebsite() {
      //computed by this stage
      urls = [u1,u2,u3,u4,l5,u6,u7,u8,u9];
    
      var promises = throttle(urls,1,myfunction);
    
      // myfunction returns a Q promise and takes a considerable 
      // amount of time to resolve (approximately 2-5 minutes)
    
      Q.all(promises).then(function(results){
          //work with the results of the promises array
      });
    }
    

    你可以在一个then()块中请求一个新的url

    myFunction(urls[0]).then(function(result) {
      myFunction(urls[1]).then(function(result) {
        myFunction(urls[2]).then(function(result) {
          ...
        });
      });
    });
    

    当然,这将是它的动态行为。 一旦解决了承诺,我会保留一个队列并将一个URL解除队列。 然后再提出一个请求。 也许有一个与搜索结果相关的哈希对象。

    第二个要点:

    var urls = ...;
    var limit = ...;
    var dequeue = function() {
      return an array containing up to limit
    };
    
    var myFunction = function(dequeue) {
      var urls = dequeue();
    
      $q.all(process urls);
    };
    
    myFunction(dequeue).then(function(result) {
      myFunction(dequeue).then(function(result) {
        myFunction(dequeue).then(function(result) {
          ...
        });
      });
    });
    

    我会这样做,它会迭代每个URL,构建一个在前一个结束时运行的promise的链,并用请求结果数组来解决。

    return urls.reduce(function(acc, url){
        return acc.then(function(results)
            return myfunction(url).then(function(requestResult){
                 return results.concat(requestResult)
            });
        });
    }, Q.resolve([]));
    

    你也可以把它变成一个帮手:

    var results = map(urls, myfunction);
    
    function map(items, fn){
        return items.reduce(function(acc, item){
            return acc.then(function(results)
                return fn(item).then(function(result){
                     return results.concat(result)
                });
            });
        }, Q.resolve([])
    }
    

    请注意, bluebird承诺库有一个简化这种事情的帮手。

    return Bluebird.map(urls, myfunction, {concurrency: 1});
    

    这里是我为Q创建一个节制map函数的刺。

    function qMap(items, worker, concurrent) {
        var result = Q.defer();
        var work = [];
        var working = 0;
        var done = 0;
    
        concurrent = parseInt(concurrent, 10) || 1;
    
        function getNextIndex() {
            var i;
            for (i = 0; i < items.length; i++) {
                if (typeof work[i] === "undefined") return i;
            }
        }
        function doneWorking() {
            working--;
            done++;
            result.notify( +((100 * done / items.length).toFixed(1)) );
            if (!startWorking() && done === items.length) {
                result.resolve(work);
            }
        }
        function startWorking() {
            var index = getNextIndex();
            if (typeof index !== "undefined" && working < concurrent) {
                working++;
                work[index] = worker(items[index]).finally(doneWorking);
                return true;
            }
        }
        while (startWorking());
        return result.promise;
    }
    

    它接受

  • 要处理的items数组(在您的案例中为URL),
  • 一个worker (它必须是一个接受物品并返回承诺的函数)
  • 以及在任何给定时间处理concurrent项目的最大值。
  • 它返回

  • 一个承诺和
  • 当所有工人完成工作后,就会解决一系列落实的承诺。
  • 它不会失败,您必须检查个别承诺以确定整个操作状态。

    在你的情况下,你会像那样使用它,例如有15个并发请求:

    // myfunction returns a Q promise and takes a considerable 
    // amount of time to resolve (approximately 2-5 minutes)
    
    qMap(urls, myfunction, 15)
    .progress(function (percentDone) {
        console.log("progress: " + percentDone);
    })
    .done(function (urlPromises) {
        console.log("all done: " + urlPromises);
    });
    
    链接地址: http://www.djcxy.com/p/23465.html

    上一篇: Limit Q promise concurrency in Node js

    下一篇: Merge two commits into one and push to remote repo