我正在开发包含Request module的节点应用。我需要触发多个请求,然后在完成所有操作后执行操作。这时,我有:
const request = require('request');
let urls = [GetUrl('id1'), GetUrl('idX'), ...);
for (let url of urls) {
let u = request.get(url);
// now what?
}
我无法弄清楚request.get返回的内容。我知道它是异步运行的。但我不知道它是ES 6的承诺,还是一些承诺库或其他完全不同的东西。
任何人都可以告诉我如何在所有请求完成后执行操作吗?
谢谢!
答案 0 :(得分:0)
您可以使用q.js来满足get函数并等待所有作业完成
var Q = require("q");
var job = function(id) {
return Q.nbind(reqest.get, GetUrl(id));
};
let urls = [job('id1'), job('idX'), ...]);
Q.all(urls)
.then(function(values) {
///do something here
})
答案 1 :(得分:0)
如果您需要等待所有响应,则无法使用常规循环。由于您拥有数组中的所有网址,因此最好使用async.each
:
async.each(urls, function(url, eachCallback) {
request.get(url, function(err) {
// do something else
eachCallback();
}
}, function(err) {
// Done
}
基本上,async.each
接受三个参数:
eachCallback
函数。请注意,人们往往忘记在任务功能中拨打eachCallback
。这将导致func2
未被执行。
如果您不希望同时进行此操作。您可以改用async.eachSeries
。它执行相同的操作,除了按顺序调用任务函数,并且只有在调用eachCallback
。
如果您想继续使用并发任务。您可能需要考虑使用async.eachLimit
eachLimit
和each
之间的区别是,eachLimit
需要一个作为参数#2传递的数字:(async.eachLimit(urls, 10, func1, func2)
)。< / p>
这是一个很好的做法,特别是如果你正在做一些耗尽机器资源的事情(比如做HTTP请求)。我在上一段中给出的例子将同时执行func1
10个。
您可以在async库存储库中阅读更多内容。
答案 2 :(得分:0)
Bluebird具有允许“限制”的额外好处。
var Promise = require('bluebird');
var request = require('request-promise'); // since we'll be using promises
Promise.map(arrayOfUrls, function(url){
return request(url)
.then(function(data){
return JSON.parse(data); // format / manipulate your data
})
}).then(function(results){
// results will be an array of JSON objects
})
这将以节点可以处理它们的速度快速调度所有请求。如果它是您自己的服务器,那可能没问题但是为了防止“太多请求错误”,请将以下内容添加到您的map
电话
Promise.map(arrayOfUrls, function, { concurrency: 4 });
// no more than 4 requests will run at once. Thanks Bluebird
答案 3 :(得分:0)
您也可以使用co。它是基于发电机的。
var co = require('co');
var request = require('request-promise');
co(function *() {
var urls = ['http://a', 'http://b'];
var results = yield urls.map(x => request(x));
console.log(results);
});
顺便说一下,您可以使用bluebird来修改现有的回调样式库。
var co = require('co');
var promisifyAll = require('bluebird').promisifyAll;
var request = promisifyAll(require('request'), {multiArgs: true});
co(function *() {
var urls = ['http://a', 'http://b'];
var results = yield urls.map(x => request.getAsync(x));
console.log(results.map(x => [x[0].statusCode, x[1]]));
});
即使您将使用ES7 async/await,更改也很小。 目前,以下需要Babel。
import 'babel-polyfill';
import request from 'request-promise';
(async () => {
let urls = ['http://foldl.com/', 'http://pig-brewing.com'];
let results = await Promise.all(urls.map(x => request(x)));
console.log(results);
})();