2

I have to implement a logic like this:

var express = require('express'),
    request = require('request');

var array = [
  { url: 'http://www.example1.com' },
  { url: 'http://www.example2.com' },
];

express.Router().get('/job', function (req, res) {
  results = [];
  array.forEach(function (item) {
    request(item.url, function (error, response, body) {
      if (!error && response.statusCode == 200) {
        results.push(body);
      }
  });
  res.json(results); // <== wrong, results array is empty, here...
});

How do I call res.json(results) being sure forEach loop is ended?

UPDATE: it is not a duplicate of suggested answer!

I need to res.json() when all requests are completed, and not when forEach loop is finished... :-(

MarcoS
  • 17,323
  • 24
  • 96
  • 174

3 Answers3

3

A simple way to accomplish this:

var express = require('express'),
    request = require('request');

var array = [
  { url: 'http://www.example1.com' },
  { url: 'http://www.example2.com' },
];

//store number of completed calls
var completed = 0;

express.Router().get('/job', function (req, res) {
  results = [];
  array.forEach(function (item) {
    request(item.url, function (error, response, body) {
      if (!error && response.statusCode == 200) {
        results.push(body);

        completed = completed + 1; //iterate counter
        onComplete(); //attempt completion
      }
  });

  function onComplete(){
    if(completed != array.length) {
      return;
    }
    res.json(results); 
    // ... rest of code that relies on results
  };

});
Jesse Kernaghan
  • 4,544
  • 2
  • 18
  • 25
2

You can use asnyc series to achieve this. Something like this:

var express = require('express'),
    request = require('request');
    async = require('async);

...

async.series([
    function(callback) {
        request('http://www.example1.com', function (error, response, body) {
            if (!error && response.statusCode == 200) {
                callback(null, body);
            }
        });
    },
    function(callback) {
        request('http://www.example2.com', function (error, response, body) {
            if (!error && response.statusCode == 200) {
                callback(null, body);
            }
        });
    }
], function(err, res) {
    res.json(res);
});
Alexandr Lazarev
  • 12,554
  • 4
  • 38
  • 47
1

You should use promises! (This example works with last version of node because supports native promises)

var arrayPromises = [];

array.forEach(function (item) {

   arrayPromises.push(new Promise(function(resolve, reject) {
       request(item.url, function (error, response, body) {
          if (!error && response.statusCode == 200) {
             resolve(body);
          }else{
            resolve();
          }
       });
   }));
});

Promise.all(arrayPromises).then(function(results){
  res.json(results);
});
Marco Talento
  • 2,335
  • 2
  • 19
  • 31