Intro
Do you know Async.js? It is a javascript framework helping deal with async functions. Let's imagine we want to render some html template:compare_two_items_html = function(item_1, item_2) {
return _.template("item #<%= item_1.id %>: <%= item_1.price %> USD vs. item #<%= item_2.id %>: <%= item_2.price %> USD");
}
And we have function of loading item:
load_item = function(id, callback) {
$.getJSON("/items/" + id, callback);
};
To render this, we should write something like that:
load_item(5, function(item_1) {
load_item(12, function(item_2) {
$("#compare_items").html(compare_two_items_html(item_1, item_2));
});
});
A little bit messy. Imagine if we had more then 2 dependencies.
Async.js
Parallel
With Async.js we could have code like this:
async.parallel([
function(callback) {
load_item(5, function(item) {
callback(null, item);
});},
function(callback) {
load_item(12, function(item) {
callback(null, item);
});}], function(err, results) {
$("#compare_items").html(compare_two_items_html(results[0], results[1]));
});
function(callback) {
load_item(5, function(item) {
callback(null, item);
});},
function(callback) {
load_item(12, function(item) {
callback(null, item);
});}], function(err, results) {
$("#compare_items").html(compare_two_items_html(results[0], results[1]));
});
Now these 2 requests are made in parallel!
Waterfall
What if we could not make the second request, before first is finished? We should use async.waterfall:
async.waterfall([
function(callback) {
load_user(8, function(user) {
callback(null, user);
});},
function(user, callback) {
load_user_items(user, function(items) {
callback(null, user, items);
});},
function(user, items, callback) {
$("#user_items").html(render_user_and_items(user, items));}
]);
function(callback) {
load_user(8, function(user) {
callback(null, user);
});},
function(user, callback) {
load_user_items(user, function(items) {
callback(null, user, items);
});},
function(user, items, callback) {
$("#user_items").html(render_user_and_items(user, items));}
]);
jQuery.Deferred
Have you ever heard about jQuery.Deferred? It is inside your jQuery right now! All ajax methods return $.Deferred object. So, lets modify our load_item function:
load_item = function(id) {
return $.getJSON("/items/" + id);
};
return $.getJSON("/items/" + id);
};
Parallel
$.when(load_item(5), load_item(12)).then(function(item_1, item_2) {
$("#compare_items").html(compare_two_items_html(item_1, item_2));
});
$("#compare_items").html(compare_two_items_html(item_1, item_2));
});
Waterfall
load_user(8).pipe(function(user) {
return $.Deferred(function() {
var deferred = this;
load_user_items(user.id).then(function() {
deferred.resolve(user, items)
});
});
}).then(function(items) {
$("#user_items").html(render_user_and_items(user, items));
});
return $.Deferred(function() {
var deferred = this;
load_user_items(user.id).then(function() {
deferred.resolve(user, items)
});
});
}).then(function(items) {
$("#user_items").html(render_user_and_items(user, items));
});
Looks not very nice :) If You know, how to make it prettier, let me know!
Good luck!