0

I want to make an http call for each element in an array, and combine all the responses into a single array, like so:

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

I'm looking at the async module, but I'm not really sure how to use it.

3
  • You might want to use async library. Commented Dec 9, 2013 at 6:30
  • What do you think about the issues in Korea? Commented Dec 9, 2013 at 6:51
  • @askkirati, as I mentioned in my question, I'm aware of the async module, but I don't see how I can make the requests in parallel and get the results in an array. If you know how to do that, please add it as an answer. Commented Dec 9, 2013 at 19:29

3 Answers 3

2

Try this, should work. You may want to try mapLimit to limit the no of parallel requests or mapSeries to do it in order.

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

for your example I need to see your get_options function. is it synchronous? if yes you can do this

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

If your get_options is asynchronous and accepts callback do following:

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);
});
Sign up to request clarification or add additional context in comments.

Comments

1

using async library's map function you can

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 Comments

this will give me an array of options for the request calls. How do I make the calls in parallel?
I think I've updated it to answer your question. The makeRequest function collects the options and makes the request for each item in the array in parallel. The request data is then put into a result array.
0

If you're interested in using promises here is an answer for that as well:

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

This uses the Q promises library. You would use it like this:

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

3 Comments

@sibbl: Why is var httpGet = function()... preferred over function httpGet()... in this instance? I'm familiar with the difference theoretically but never found much a difference in the field.
It isn't. Unfortunately you have to change at least 6 characters to make an edit... I preferred to change this because it doesn't change the original content at all instead of leaving the "response" instead of "res" typo. I'd appreciate help if there's a way to solve this in a better way next time.
Seems reasonable to me, I was just curious if there was a more theoretical reason. But SO reasons make sense. LOLz!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.