当前位置: 首页 > 知识库问答 >
问题:

限制节点js中的Q promise并发

庾勇军
2023-03-14

有没有办法限制节点js中一次执行的并发Qpromise的数量?

我正在构建一个web scraper,它必须请求并解析3000多个页面,并且在没有限制的情况下,我提出的一些请求没有及时响应,因此连接停止,所需的响应(html代码)变得不可用。

为了解决这个问题,我发现限制请求的数量可以解决我的问题。

我曾尝试过以下方法,但均无效:

  • Qpromise中的并发限制-节点

我需要请求一个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
  });
}

共有3个答案

喻昀
2023-03-14

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

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

当然,这将是它的动态行为。一旦一个promise被解决,我会管理一个队列并退出一个网址。然后提出另一个要求。并且可能有一个hash对象将urls与结果相关联。

第二步:

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) {
      ...
    });
  });
});
张银龙
2023-03-14

这是我为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;
}

它接受

  • 要处理的项的数组(URL,在您的例子中),
  • 工作者(必须是接受项目并返回promise的函数)
  • 以及在任何给定时间要处理的并发项的最大值

它返回

  • promise和
  • 当所有工人都完成时,解析为一系列已确定的promise

如果没有失败,您必须检查各个promise,以确定操作的总体状态。

在您的情况下,您可以这样使用它,例如,与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);
});
冀啸
2023-03-14

我会这样做,它将迭代每个URL,构建一个promise链,当前一个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([])
}

请注意,bluebirdpromise库有一个帮助器来简化这类事情。

return Bluebird.map(urls, myfunction, {concurrency: 1});
 类似资料:
  • 有没有使用Qpromise库限制promise并发的方法? 这个问题有点与如何限制Qpromise并发有关? 但问题是我正试图这样做: 真正的用例是: 从DB获取帖子 循环DB中的每个帖子,如 对于每个帖子做task1,task2,task3(检索社交计数器,检索评论计数等) 在DB中保存新的文章数据。 但问题是node同时执行所有帖子的所有任务,比如同时向facebook询问500篇帖子的“喜欢

  • 如何编写限制Qpromise并发的方法? 例如,我有一个方法。 我希望一次生成不超过5个进程,但对调用代码是透明的。 我需要实现的是一个带有签名的函数 我可以这样称呼他 我已经开始编写我的版本,但我想知道是否有人有一个简洁的实现,我可以对照它进行检查。

  • 这是港口范围。我不确定这是否重要(我不确定DNAT和SNAT是否使用端口),但范围似乎远高于16K。 还有什么可能限制通过iptables/netfilter转发的并发连接的数量吗?

  • 我正在寻找下面输入和输出XML的XSLT(1.0)代码。 在输出XML中,C6元素下可以有任何子节点。在下面的XML中,我放了CN元素,但它可以是任何名称。 输入XML- 所需的输出XML- 先谢谢你。

  • 我有一个集合,其中显示了用户最喜爱的电影列表。这是一个示例数据集。。。 现在给定_id和一部电影 如果我需要把这个加到watched_movies,在Node.js/MongoDB,我相信唯一的方法是 使用“查找”查找文档 步骤#2基于此处的示例http://mongodb.github.io/node-mongodb-native/markdown-docs/insert.html 有更好的方法

  • 我用图表js设置了一个折线图。在这张图中,我的点太大了,但这不是我的问题。有太多的点。 有没有办法限制点数? 每5分一分将是一个很好的解决方案。