Node.js – Use promises for multiple node requests

expressnode.jspromise

With the request library, is there a way to use promises to simplify this callback?

  var context = {};

  request.get({
    url: someURL,
  }, function(err, response, body) {

    context.one = JSON.parse(body);

    request.get({
      url: anotherURL,
    }, function(err, response, body) {
      context.two = JSON.parse(body);

      // render page
      res.render('pages/myPage');
    });
  });

Best Answer

Here's a solution using the Bluebird promises library. This serializes the two requests and accumulates the results in the context object and rolls up error handling all to one place:

var Promise = require("bluebird");
var request = Promise.promisifyAll(require("request"), {multiArgs: true});

var context = {};
request.getAsync(someURL).spread(function(response, body) {
    context.one = JSON.parse(body);
    return request.getAsync(anotherURL);
}).spread(response, body)
    context.two = JSON.parse(body);
    // render page
    res.render('pages/myPage');
}).catch(function(err) {
    // error here
});

And, if you have multiple URLs, you can use some of Bluebirds other features like Promise.map() to iterate an array of URLs:

var Promise = require("bluebird");
var request = Promise.promisifyAll(require("request"), {multiArgs: true});

var urlList = ["url1", "url2", "url3"];
Promise.map(urlList, function(url) {
    return request.getAsync(url).spread(function(response,body) {
        return [JSON.parse(body),url];
    });
}).then(function(results) {
     // results is an array of all the parsed bodies in order
}).catch(function(err) {
     // handle error here
});

Or, you could create a helper function to do this for you:

// pass an array of URLs
function getBodies(array) {
    return Promise.map(urlList, function(url) {
        return request.getAsync(url).spread(function(response.body) {
            return JSON.parse(body);
        });
    });
});

// sample usage of helper function
getBodies(["url1", "url2", "url3"]).then(function(results) {
    // process results array here
}).catch(function(err) {
    // process error here
});