0

Currently I am building a web application using Node and Express. The application is required to access another API and push that data to the user. I wrote the API wrapper using the request library. An example API function looks like this:

Robinhood.prototype.getAccount = function(callback) {
  var options = {
    url: endpoints.accounts,
    headers: this.headers,
    method: 'GET',
    strictSSL: true,
    json: true
  };
  request(options, callback);
};

Oftentimes it is necessary to push this data to a view. I do this by using express routes; however, it is oftentimes necessary to make multiple function calls to retrieve all of the information I need. This creates a situation familiar to us as callback-hell:

app.get('/main', isLoggedIn, function(req, res) {
        var object = {
            user : req.user
        };

        var accountData = new Robinhood(req.user.local.rhtoken).getAccount(function(err, httpResponse, body) {
            if (err) throw err;
            object.account = body;
            var portfolioData = new Robinhood(req.user.local.rhtoken).getInvestmentProfile(function(err, httpResponse, body) {
                if (err) throw err;
                object.portfolio = body;
                var userData = new Robinhood(req.user.local.rhtoken).getUser(function(err, httpResponse, body) {
                    if (err) throw err;
                    object.userData = body;

                    console.log(object);
                    res.render('main_pages/maindashboard.ejs', object);
                });
            });
        });
    });

Not only is this horrible to read, but it also makes the code more difficult to extend if I want to pass another piece of the data to the view. After some research, I've seen that the best methods of solving this are with promises and generators. I'm aware that the proper solution to this may be using generators, but I think I need a more solid understanding of promises before I attempt to implement one. I looked into using the Q promise library for Node, however, I found that Q.fcall only works when the function returns a value, which, in this case, it doesn't. The Q library documentation mentions two concepts, Deferreds and Q.Promises, that I think could be helpful, but I don't understand how to implement either of these things. So my question is, how can I either rewrite the API function to return a promise, or how can I rewrite the code to call the function and retrieve the data using promises?

Chandler Freeman
  • 899
  • 1
  • 10
  • 25
  • You cannot use generators without promises anyway, so you'll need to understand and use promises in the first place for either. – Bergi Nov 06 '15 at 12:54
  • You are looking for [`Q.nfcall` and `Q.ninvoke` and others](https://github.com/kriskowal/q/wiki/API-Reference#interfacing-with-nodejs-callbacks), not `fcall`. – Bergi Nov 06 '15 at 12:55

1 Answers1

0

The general concept is that you "promisify" the async interfaces that you want to use. This creates a new interface that uses the existing callback interface, but let you interact only with a promise-based interface.

You can see several examples of how to promisify an interface in these references:

Node.js: serial operations with branching

Make an Api call with javascript promises in recursion

In addition, promises libraries like Bluebird contain functions for automatically creating a promise interface.

Community
  • 1
  • 1
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Thank you, after this I'm currently designing my API to be able to be used by both promises and callbacks – Chandler Freeman Nov 06 '15 at 08:33
  • @ChandlerFreeman - if I was doing that, I'd design the interface to work on promises internally since it offers superior features for managing async operations and then to surface the callback interface, you can put a callback wrapper around the top level to offer an additional callback based API. – jfriend00 Nov 06 '15 at 23:30