Keroles
Keroles

Reputation: 13

Return results of a request loop

I want to make an initial request to get a list of IDs, and then make a request for each individual id and store the JSON results in an array. Here is the code basics:

request(options, function(err, resp, body){
 ids = (JSON.parse(body))[ids];
 results=[];
 for(id in ids){
  options.path='/api/example/' + ids[id];
  request(options, function(err, resp, body){
   results.push(JSON.parse(body));
  })
 }
 res.send(results);
})

When I run this, results is still an empty array and when I put res.send(results) in the inner request function,it only captures one result and not all of them. Any ideas?

Upvotes: 0

Views: 78

Answers (1)

Matías Fidemraizer
Matías Fidemraizer

Reputation: 64933

Most NodeJS operations are asynchronous. If some function requires a callback it means that there's no guarantee that after invoking it you'll get the result.

When you perform N requests using the for loop you're starting N asynchronous operations and each one's callback will be called when the underlying asynchronous operation has ended.

There're many options here to solve the issue.

For example, you can use Q, a Promise pattern implementation, to enqueue async promises and wait untill all have been resolved:

request(options, function(err, resp, body){
 // First of all, you create a deferred object
 var deferred = Q.defer();

 // Also, you create an array to push promises
 var promises = [];

 ids = (JSON.parse(body))[ids];
 results=[];
 for(id in ids){
  options.path='/api/example/' + ids[id];

  // You create a promise reference, and later
  // you add it to the promise array
  var promise = deferred.promise;
  promises.push(promise);

  request(options, function(err, resp, body){
   results.push(JSON.parse(body));

   // whenever an async operation ends, you resolve its promise
   deferred.resolve();
  })
 }

 // Now you wait to get all promises resolved (i.e. *done*), and then your 
 // "results" array will be filled with the expected results!
 Q.all(promises).then(function() {
     res.send(results);
 });
});

Upvotes: 1

Related Questions