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?