【问题标题】:node.js : make http calls in for loopnode.js:在 for 循环中进行 http 调用
【发布时间】:2013-12-26 02:41:17
【问题描述】:

我想对数组中的每个元素进行 http 调用,并将所有响应合并到一个数组中,如下所示:

result = [] ; i = 0
for item in array
  options = get_options(item)
  request options, (err, res, body)->
    result[i++] = body

// when all calls are done, console.log the 'result' array

我正在查看异步模块,但我不确定如何使用它。

【问题讨论】:

  • 你可能想使用异步库。
  • 您如何看待韩国的问题?
  • @askkirati,正如我在问题中提到的,我知道异步模块,但我不知道如何并行发出请求并在数组中获取结果。如果您知道该怎么做,请将其添加为答案。

标签: javascript node.js http asynchronous coffeescript


【解决方案1】:

试试这个,应该可以的。您可能想尝试使用 mapLimit 来限制并行请求的数量,或者尝试使用 mapSeries 来按顺序执行。

var async = require('async');
var request = require('request');
async.map(['url1', 'url2'], function(item, callback){
  request(item, function (error, response, body) {
    callback(error, body);
  });
}, function(err, results){
  console.log(results);
});

对于您的示例,我需要查看您的 get_options 函数。是同步的吗?如果是,你可以这样做

var async = require('async');
var request = require('request');
var options;
async.map([item1, item2], function(item, callback){
  options = get_options(item);
  request(options, function (error, response, body) {
    callback(error, body);
  });
}, function(err, results){
  console.log(results);
});

如果您的 get_options 是异步的并接受回调,请执行以下操作:

var async = require('async');
var request = require('request');
async.map([item1, item2], function(item, callback){
  get_options(item, function(err, option){
    if(err) {
      callback(err);
    }
    else{
      request(options, function (error, response, body) {
       callback(error, body);
      });
    }
  });
}, function(err, results){
  console.log(results);
});

【讨论】:

    【解决方案2】:

    使用异步库的map函数可以

    var makeRequest = function(item, callback){
        var options = get_options(item);
        // handle http errors and getting access to body properly
        http.get(options,res){
            callback(null, res)
        }
    }
    
    async.map(['item1','item2','item3'], makeRequest(item, callback), function(err, results){
        //check errors do stuff with results
    });
    

    【讨论】:

    • 这将为我提供请求调用的一系列选项。如何并行调用?
    • 我想我已经更新了它来回答你的问题。 makeRequest 函数收集选项并对数组中的每个项目进行并行请求。然后将请求数据放入结果数组中。
    【解决方案3】:

    如果您对使用 Promise 感兴趣,这里也是一个答案:

    var Q = require('q');
    var http = require('http');
    
    var httpGet = function(url) {
      var data = "", defer = Q.defer();
      http.get(url, function (res) {
        var content_length = parseInt(res.headers['content-length'], 10);
        var total_downloaded = 0;
        if (res.statusCode !== 200) {
          defer.reject("HTTP Error " + res.statusCode + " for " + url);
          return;
        }
        res.on("error", defer.reject);
        res.on("data", function (chunk) {
          data += chunk;
          total_downloaded += chunk.length;
          var percentage = Math.floor((total_downloaded / content_length) * 100);
          defer.notify(percentage);
        });
        res.on("end", function () { defer.resolve(data); });
      });
      return defer.promise;
    }
    

    这使用Q promises 库。你可以这样使用它:

    var promise = httpGet("http://example.com/");
    promise.then(function (data) {
      // Do something with data.
    }, function (reason) {
      // Do something with the error
    }, function (progress) {
      // Do something with the progress update (% so far)
    });
    

    【讨论】:

    • @sibbl:为什么在这种情况下var httpGet = function()...function httpGet()... 更受欢迎?我在理论上熟悉这种差异,但在该领域从未发现太大差异。
    • 不是。不幸的是,您必须更改至少 6 个字符才能进行编辑...我更喜欢更改它,因为它根本不会更改原始内容,而不是留下“响应”而不是“res”错字。如果下次有办法以更好的方式解决此问题,我将不胜感激。
    • 对我来说似乎是合理的,我只是好奇是否有更理论上的原因。但是 SO 的原因是有道理的。哈哈!
    猜你喜欢
    • 1970-01-01
    • 2018-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-11
    相关资源
    最近更新 更多