Have you ever need to wait for several, unrelated asynchronous functions or processes on NodeJS in order to met dependencies of a last request/method/function/etc? I’m really sure you have, and it can be a pain if you do not know how to properly handle it. The worst and common case is having each one of this nested on then previous one.
There is a really easy and common way I’ve seen lately, that is by using Async.js which is not bad, but it is not that good either, mainly cause it is not a standard. If you want (and you should really want!) a standard way to do such tasks (the right way) then you should start using Promises.
From CommonJS:
Promises provide a well-defined interface for interacting with an object that represents the result of an action that is performed asynchronously, and may or may not be finished at any given point in time. By utilizing a standard interface, different components can return promises for asynchronous actions and consumers can utilize the promises in a predictable manner. Promises can also provide the fundamental entity to be leveraged for more syntactically convenient language-level extensions that assist with asynchronicity.
In this example I’ll be demotrating how to use Q (Promises/B proposal by Kris Kowal) in 3 different use cases: standard functions, NodeJS like functions (callbacks) and finally a simple deferred implementation.
Standard Functions
Just a common JavaScript function that receives 0 or more parameters and returns a value.
// Module Dependencies
var Q = require('q');
// Some random numbers to play with, and a queue to keep the code readable
var numbers = [Math.random(), Math.random(), Math.random(), Math.random(), Math.random()],
queue = [];
// A slow useless function to exemplify
function slowFunction(times) {
var i = 0,
times = parseInt(1000000000 * times);
while (i < times) {
i += 1;
}
return times;
}
// For each random number, create a function call and addit to the queue
numbers.forEach(function(number) {
queue.push(Q.call(slowFunction, this, number));
});
// Q.all: execute an array of 'promises' and 'then' call either a resolve
// callback (fulfilled promises) or reject callback (rejected promises)
Q.all(queue).then(function(ful) {
// All the results from Q.all are on the argument as an array
console.log('fulfilled', ful);
}, function(rej) {
// The first rejected (error thrown) will be here only
console.log('rejected', rej);
}).fail(function(err) {
// If something whent wrong, then we catch it here, usually when there is no
// rejected callback.
console.log('fail', err);
}).fin(function() {
// Finally statemen; executed no matter of the above results
console.log('finally');
});
Output
fulfilled [ 149412936, 355777001, 942437362, 998285385, 448049797 ] finally
NodeJS like functions (Inverse of Control)
Most NodeJS callbacks will return 1 or 2 params, first one being the error (if any) and the second the result.
// Module Dependencies
var Q = require('q'),
request = require('request');
// Some URLs to play with, and a queue to keep the code readable
var urls = ['google.com', 'twitter.com', 'facebook.com'],
queue = [];
// A standard NodeJS function: a parameter and a callback; the callback
// will return error (if any) as first parameter and result as second
// parameter.
function fetchUrl(url, callback) {
request({
url: 'http://' + url
}, function(err, res, body) {
if (err) {
callback(err, null);
} else {
// For brevity, on this example we are only interested on the headers
callback(null, res.headers);
}
});
}
// For each url, create a function call and addit to the queue
urls.forEach(function(url) {
queue.push(Q.ncall(fetchUrl, this, url));
});
// Q.all: execute an array of 'promises' and 'then' call either a resolve
// callback (fulfilled promises) or reject callback (rejected promises)
Q.all(queue).then(function(ful) {
// All the results from Q.all are on the argument as an array
console.log('fulfilled', ful);
}, function(rej) {
// The first rejected (error thrown) will be here only
console.log('rejected', rej);
}).fail(function(err) {
// If something whent wrong, then we catch it here, usually when there is no
// rejected callback.
console.log('fail', err);
}).fin(function() {
// Finally statemen; executed no matter of the above results
console.log('finally');
});
Output (Omitted in sake of brevity)
fulfilled [ { ... }, { ... }, { ... } ]
finally
Deferred
On a previous post I exemplified how to use jQuery’s When which is the same concept of Promise. This time this is the NodeJS version of a Promise.
// Module Dependencies
var Q = require('q'),
request = require('request');
// Some URLs to play with, and a queue to keep the code readable
var urls = ['google.com', 'twitter.com', 'facebook.com'],
queue = [];
// A standard NodeJS function: a parameter and a callback; the callback
// will return error (if any) as first parameter and result as second
// parameter.
function fetchUrl(url) {
// The 'deferred' object, base of the Promises proposal on CommonJS
var deferred = Q.defer();
request({
url: 'http://' + url
}, function(err, res, body) {
if (err) {
// An error? Reject the promise
deferred.reject(err);
} else {
// Success! Resolve the promise
// For brevity, on this example we are only interested on the headers
deferred.resolve(res.headers);
}
});
// Return only the promise which will allow the usage of 'when' and 'then'
// among others
return deferred.promise;
}
// For each url, create a function call and addit to the queue
urls.forEach(function(url) {
queue.push(fetchUrl(url));
});
// Q.all: execute an array of 'promises' and 'then' call either a resolve
// callback (fulfilled promises) or reject callback (rejected promises)
Q.all(queue).then(function(ful) {
// All the results from Q.all are on the argument as an array
console.log('fulfilled', ful);
}, function(rej) {
// The first rejected (error thrown) will be here only
console.log('rejected', rej);
}).fail(function(err) {
// If something whent wrong, then we catch it here, usually when there is no
// rejected callback.
console.log('fail', err);
}).fin(function() {
// Finally statemen; executed no matter of the above results
console.log('finally');
});
Output (Omitted in sake of brevity)
fulfilled [ { ... }, { ... }, { ... } ]
finally
Hopefully with this 3 examples you now know a different, standard, clean and elegant way to solve those more than common situations in NodeJS (and also on the browser if you do not use jQuery).
Questions? Comments?

Pingback: How to wait for 2+ asynchronous responses on NodeJS (CommonJS Promises) | Erick Ruiz de Chavez | Modern web development | Scoop.it
I find something like this much easier to read.
https://gist.github.com/2978541
// Module Dependencies
var step = require(‘step’)
, request = require(‘request’)
, inspect = require(‘util’).inspect
// Some URLs to play with, and a queue to keep the code readable
, urls = ['google.com', 'twitter.com', 'facebook.com']
step
( function() {
var self = this
// For each url, create a parallel step
urls.forEach(function(url) {
request({url: ‘http://’+url}, self.parallel()) } ) }
, function(err) {
var results = Array.prototype.slice.call(arguments, 1)
// handle errors
if (err) {
console.log(“rejected “+err) }
// print results
console.log(“fulfilled “+results.map(function(r){return inspect(r.headers)}))
// eh, we’re done
console.log(“finally”) } )
First of all, thanks for taking your time to read my blog post.
Every problem have several solutions, based on the experience and expertise of the developer solving it. Step is not a Promise implementation, it is just a flow control utility. The example is intended to show some of the functions available on “Q” API, including some error handling and flow recovering which all good programmers need to implement. If I was speaking about code readability I would have done something like the example below. Also, as a word of advice, nested callbacks are far from being readable.
var Q = require('q'), request = require('request'), queue = []; function fetchUrl(url, callback) { request({ url: 'http://' + url }, function(err, res, body) { if (err) { callback(err, null); return; } callback(null, res.headers); }); } ['google.coms', 'twitter.com', 'facebook.com'].forEach(function(url) { queue.push(Q.ncall(fetchUrl, this, url)); }); Q.all(queue).then(function(ful) { console.log('fulfilled', ful); }).fail(function(rej) { console.log('rejected', rej); });In your example there is no finally statement so, to do a fair comparison I removed it from my new example. Let’s see what happens if I change the first URL to a non existent one: google.coms
Your example’s output:
rejected Error: socket hang up C:\Users\501677641\Node\node_modules\step\lib\step.js:39 throw arguments[0]; ^ TypeError: Cannot read property 'headers' of undefined at C:\Users\501677641\Node\step.js:31:23 at Array.map (native) at Function.<anonymous> (C:\Users\501677641\Node\step.js:30:40) at next (C:\Users\501677641\Node\node_modules\step\lib\step.js:51:23) at Request._callback (C:\Users\501677641\Node\node_modules\step\lib\step.js:83:14) at Request.callback (C:\Users\501677641\Node\node_modules\request\main.js:119:22) at Request.<anonymous> (native) at Request.emit (events.js:70:17) at Request.<anonymous> (C:\Users\501677641\Node\node_modules\request\main.js:521:16) at Request.emit (events.js:67:17)Wait! what happened there? Isn’t supposed to handle errors?
Mine’s:
rejected { [Error: socket hang up] code: 'ECONNRESET' }Ok! there is it, implicit error handler.
Finally, if we speak about code validity (which is far from be a synonym of code readability) I JSHinted both yours and mine:
Yours:
Microsoft (R) Windows Script Host Version 5.8 Copyright (C) Microsoft Corporation. All rights reserved. File "C:\Users\501677641\Node\step.js" Line 4 character 29: Bad line breaking before ','. inspect = require('util').inspect Line 8 character 56: Missing semicolon. urls = ['google.coms', 'twitter.com', 'facebook.com'] Line 11 character 20: Missing semicolon. var self = this Line 17 character 26: Missing semicolon. }, self.parallel()) Line 18 character 7: Missing semicolon. }) Line 19 character 3: Bad line breaking before ','. } Line 22 character 59: Missing semicolon. var results = Array.prototype.slice.call(arguments, 1) Line 26 character 37: Missing semicolon. console.log("rejected " + err) Line 31 character 32: Missing semicolon. return inspect(r.headers) Line 32 character 8: Missing semicolon. })) Line 35 character 27: Missing semicolon. console.log("finally") Line 36 character 5: Missing semicolon. }) Implied globals: require: 2,3,4 console: 26,30,35 [Finished]Mine:
Microsoft (R) Windows Script Host Version 5.8 Copyright (C) Microsoft Corporation. All rights reserved. File "C:\Users\501677641\Node\q-ncall-brief.js" Implied globals: require: 1,2 console: 22,24 [Finished]Pingback: How to wait for 2+ asynchronous responses on NodeJS (CommonJS Promises) | kernicPanel | Scoop.it
JSHint tests for a particular coding style. I’m not interested in arguing about coding style since the topic has already been covered ad nauseam. I disagree with your comment about nested callbacks. Do you break out a named function for every forEach loop you right? Not only do I think that it makes code harder to read, but it is not the most common practice in high quality javascript code that I’ve read. Or do you mean that step itself is a function? That’s what I like about it. It lends itself to a more functional style of coding with less moving parts.
Pingback: How to wait for 2+ asynchronous responses on NodeJS (CommonJS Promises) | Erick Ruiz de Chavez - Dougal Campbell's geek ramblings
Where is the guarantee that in the first listing:
“Q.all(queue)” will be executed only after all “number promises” are pushed to the queue (lines: 20-27…)? I thought the nodejs execute as parallel as possible, so I would assume, that Q.all(queue) could start immediately after “numbers…” initiated to execute. If it is not so, are there some links to the documentation of node.js to prove the sequential behavior (on the praxis I see – it works). Why the Q.all(queue) implicitly knows that it mus wait until the queue is ready in the previous step?
Q is a promise implementation that helps you control the flow by executing callbacks when all the methods are done, when there is some progress on them, or when something fails; it’s purpose is not to start them all at once, therefor there is no guarantee it will wait for all of the promises to be ready in order to start executing them.
Q.all aims to help you know when all your promise objects are either resolved or rejected and based on those results know if you can continue with the results of the promises or halt due to an error.
You can get more details regarding promises at http://wiki.commonjs.org/wiki/Promises
but what if some promises are not yet pushed into the queue? Does the Q get know, that someone working on the queue and it should wait until the queue ready is?