Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NodeJS: Good way to write Multiple API Calls in serial

Is there a better/more beautiful way to call multiple APIs after another (in serial) as in my example?

  var request = require('request');

  request('http://www.test.com/api1', function (error, response, body) {
    if (!error && response.statusCode == 200) {

      request('http://www.test.com/api1', function (error, response, body) {
        if (!error && response.statusCode == 200) {

          request('http://www.test.com/api1', function (error, response, body) {
            if (!error && response.statusCode == 200) {

              //And so on...

            }
          })

        }
      })

    }
  })
like image 774
Til Avatar asked Feb 19 '17 18:02

Til


3 Answers

Depending on which version of node you are using, promises should be native...

https://nodejs.org/en/blog/release/v4.0.0/

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

var request = require('request');

getRequest('http://www.test.com/api1').then(function (body1) {
    // do something with body1
    return getRequest('http://www.test.com/api2');
}).then(function (body2) {
    // do something with body2
    return getRequest('http://www.test.com/api3');
}).then(function (body3) {
    // do something with body3
    //And so on...
});

function getRequest(url) {
    return new Promise(function (success, failure) {
        request(url, function (error, response, body) {
            if (!error && response.statusCode == 200) {
                success(body);
            } else {
                failure(error);
            }
        });
    });
}
like image 107
Michael McLaughlin Avatar answered Oct 20 '22 00:10

Michael McLaughlin


Use async.series If you want to do same operation on a set of URLs, use async.map

Promise can also be used as others suggested.

If you are new with asynchronous programming, I suggest to start with async module then move to Promise (or coroutines, async/await) once you have clearer understanding.

Example:

var request = require('request');

async.series([
  function(callback) {
    request('http://www.test.com/api1', function(error, response, body) {
      if (!error && response.statusCode == 200) {
        return callback(null, response);
      }
      return callback(error || new Error('Response non-200'));
    }
  },
  function(callback) {
    request('http://www.test.com/api2', function(error, response, body) {
      if (!error && response.statusCode == 200) {
        return callback(null, response);
      }
      return callback(error || new Error('Response non-200'));
    }
  }
],
// optional callback
function(err, results) {
  if (err) {
    // Handle or return error
  }
  // results is now array of responses
});
like image 24
Sangharsh Avatar answered Oct 20 '22 00:10

Sangharsh


You can use request-promise instead of request and then you would be able to chain all the promises!

https://github.com/request/request-promise

var rp = require('request-promise');

rp(options)
.then(function (body) {
   return rp(...)
}).then(()){
   ...
}

In my honest opinion and if the order is not important you should do all the requests in parallel!

like image 36
Marco Talento Avatar answered Oct 20 '22 00:10

Marco Talento