获取多个请求

时间:2016-03-18 17:32:19

标签: javascript node.js

我正在开发包含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的承诺,还是一些承诺库或其他完全不同的东西。

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

谢谢!

4 个答案:

答案 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接受三个参数:

  1. 网址 - 要迭代的项目数组
  2. func1 - 用作每个项目执行任务的函数。每当调用此函数时,都会传递两个参数:
    • url - 数组中的项目
    • eachCallback - 一个回调函数供您随时调用嘿,此任务已完成!
  3. func2 - 迭代所有项目后将执行的函数,并调用所有eachCallback函数。
  4. 请注意,人们往往忘记在任务功能中拨打eachCallback。这将导致func2未被执行。

    如果您不希望同时进行此操作。您可以改用async.eachSeries。它执行相同的操作,除了按顺序调用任务函数,并且只有在调用eachCallback

    之后

    如果您想继续使用并发任务。您可能需要考虑使用async.eachLimit eachLimiteach之间的区别是,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);
})();