JavaScript is different from other programming languages because it is asynchronous. That means that there is a possibility that several things can be happening at the same time. In other words, JavaScript doesn't wait for one thing to execute before going to the next. If you are waiting for a timeout to fire, or a response from an Ajax call or a database transaction, while the process completes, JavaScript silently moves on.
For example, this will result in the function returning "undefined":
function doSomething () { var something; setTimeout(function () { something = "a response"; }, 1000); return something; } // This will be undefined console.log(doSomething());
This can be solved by passing a callback function into the function you are calling. That's right, we're passing a function as a parameter into a function. This is JavaScript meeting Inception.
function doSomething (done) { setTimeout(function () { done("a response"); }, 1000); } doSomething(function (something) { // "a response" console.log(something); });
When the process has been completed, the callback function can be fired with all of the needed data inside of it.
I keep running into instances where I need to fire several functions and then do something after they have all completed. That is trickier because there has to be a way to know when they are all done. You can do something like this:
function thingOne (done) { setTimeout(function () { done("1st response"); }, 1000); } function thingTwo (done) { setTimeout(function () { done("2nd response"); }, 1500); } function thingThree (done) { setTimeout(function () { done("3rd response"); }, 2000); } thingOne(function (one) { thingTwo(function (two) { thingThree(function (three) { // ["1st response", "2nd response", "3rd response"] console.log([one, two, three]); }); }); });
That will work, but nesting callback functions inside of each other can get really messy. It also ignores one of the main benefits of JavaScript, which is the ability to perform multiple operations at the same time. The example above will take 4 1/2 seconds to complete because the functions aren't running at the same time.
A more efficient way to get the same sort of results would be to keep track of how many functions have finished executing. If the number matches the number we are expecting to finish, we know everything is done.
var numberOfFunctions = 2, // This is a 0-based index, so 2 really means 3 data = []; function finished () { // ["1st response", "2nd response", "3rd response"] if (data.length === numberOfFunctions) { console.log(data); } } function thingOne (done) { setTimeout(function () { done("1st response"); }, 1000); } function thingTwo (done) { setTimeout(function () { done("2nd response"); }, 1500); } function thingThree (done) { setTimeout(function () { done("3rd response"); }, 2000); } thingOne(function (one) { data.push(one); finished(); }); thingTwo(function (two) { data.push(two); finished(); }); thingThree(function (three) { data.push(three); finished(); });
That should run in about two seconds, so we've made a big improvement. The downside is that there can be a little overhead in making sure all of the functions have fired.
Today, I released a plugin for underscore that fires multiple functions at the same time and responds with a single callback once all of the functions have completed.
It basically uses the same concept as the last example, but it wraps all of the tedious code in a simpler method. It allows you to do the same thing as in the example above like this:
var things = [ function (done) { setTimeout(function () { done("1st response"); }, 1000); }, function (done) { setTimeout(function () { done("2nd response"); }, 1500); }, function (done) { setTimeout(function () { done("3rd response"); }, 2000); } ]; _.fire(things, function (data) { // ["1st response", "2nd response", "3rd response"] console.log(data); });
As you can see, using underscore fire requires significantly less code and is very readable. It's available on GitHub and NPM and the only dependency is either Underscore or Lodash.
Check out the readme on Github to see what it can do. Let me know what you think.



Sounds to me like you´re looking for smth. like promises & deferreds.
Check out this presentation from @jaubourg: http://demo.creative-area.net/jqcon2011-boston/#3
Yeah, I just ran into that presentation yesterday. It makes the way I’m handeling it look silly :)
I know this will work with jQuery, but it seems like overkill to throw jQuery on the server-side if you’re using Node. Do you know of something like this that is more suited for the server-side?
Sure:
Q and rsvp.js are two fine implementations.
They both run in node & in the browser.
https://github.com/kriskowal/q
https://github.com/tildeio/rsvp.js
+1 to @asciidisco’s suggestion. Promises/deferreds may have not always be ideal, but are generally pretty well-suited for cases like this.
Also as an aside: you may want to clarify some of your points about how “JavaScript doesn’t wait for one thing to execute before going to the next”. Though it is event-based, and modern JavaScript applications use events to prevent blocking whenever possible, the language is single-threaded, and as such when you have a long-running operation, it *does* wind up waiting for that code to finish running before it moves on. Though the single-threaded nature is easy for most people to get, how the event-based models fit in around that can be confusing for people that are new to it.
All that being said, I *am* looking forward to checking out your plugin. Sounds like it could be just the trick for certain scenarios.
Good point.
I guess I should probably clarify that I was mostly referring to asynchronous events like timeouts, intervals, ajax calls and database transactions.