限制Q在Node js中承诺并发
有没有办法限制在js节点上同时执行的并发Q promise的数量?
我正在构建一个网页报废器,它必须请求并解析更多3000多页,并且不会扼杀我所做的某些请求没有及时响应,因此连接停止,并且所需的响应(html代码)不可用。
为了反击这一点,我发现限制了我的问题消失的请求数量。
我尝试了以下方法,但无济于事:
我需要请求一个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