2016-03-18 140 views
0

我正在研究包含Request module的Node应用程序。我需要发出多个请求,然后在全部完成时执行一个操作。在这个时候,我有:获取多个请求

const request = require('request'); 

let urls = [GetUrl('id1'), GetUrl('idX'), ...); 
for (let url of urls) { 
    let u = request.get(url); 
    // now what? 
} 

我想不通什么request.get返回。我知道它是异步运行的。但是我不能说它是ES6的承诺,还是一些承诺库或其他的东西。

任何人都可以告诉我在所有请求完成后如何执行操作?

谢谢!

+0

request.get在回调函数中返回一个[http.ServerResponse](https://nodejs.org/api/http.html#http_class_http_serverresponse) – ZimSystem

回答

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 
0

您可以使用q.js到promisfy 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 
}) 
0

如果您需要等待所有的答复,你不能使用常规的循环。而且因为你在阵列中的所有网址,最好使用async.each

async.each(urls, function(url, eachCallback) { 
    request.get(url, function(err) { 
    // do something else 
    eachCallback(); 
    } 
}, function(err) { 

    // Done 
} 

基本上,async.each接受三个参数:

  1. 网址 - 项目的数组迭代
  2. func1 - 作为每个项目执行任务的函数。从阵列
  3. eachCallback的项目 - -
    • 网址的回调函数为你调用,只要你想说嘿,这任务是:只要调用这个函数,两个参数一起传递完成了!
  4. FUNC2 - 一旦你遍历所有的项目,所有eachCallback函数被调用,将执行一个功能。

请注意,人们往往会忘记在任务功能中调用eachCallback。这将导致func2未被执行。


如果你不想同时做到这一点。您可以改用async.eachSeries。它做同样的事情,除了顺序调用任务功能,并且只有在您致电eachCallback后。


如果您想继续使用并发任务。您可能要考虑使用async.eachLimiteachLimiteach之间的差异是,eachLimit需要传递为参数#2的数字:(async.eachLimit(urls, 10, func1, func2))。

这是一个很好的做法,尤其是如果你正在做耗尽机器资源的事情(比如做HTTP请求)。我在上一段中给出的例子将同时执行10个并行执行func1


您可以在async库存储库中阅读更多信息。

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为plomisify现有的回调样式库。

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,更改也很小。 目前,以下需求巴别。

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