node.js:在for循环中进行http调用

时间:2013-12-09 04:08:29

标签: javascript node.js http asynchronous coffeescript

我想对数组中的每个元素进行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

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

3 个答案:

答案 0 :(得分:2)

试试这个,应该有效。您可能希望尝试使用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);
});

答案 1 :(得分:1)

使用异步库的地图功能

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

答案 2 :(得分:0)

如果您对使用承诺感兴趣,也可以使用答案:

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