Chaining asynchronous javascript calls
The good thing about JavaScript is that its network/ajax calls are asynchronous. The bad thing about JavaScript is that its network/ajax calls are asynchronous.
It’s bad because nested calls increase complexity. Look at the following sample methods:
function f1(callback) {
console.log('f1');
if (callback != null) {
console.log('hasCallback');
callback();
}
}
function f2(callback) {
console.log('f2');
if (callback != null) {
console.log('hasCallback');
callback();
}
}
function f3(callback) {
console.log('f3');
if (callback != null) {
console.log('hasCallback');
callback();
}
}
The calls should be executed one after another.
f3(
function(){
return f2(
function()
{
return f3();
}
);
}
);
Reading or even worst writing this makes me not happy. I don’t like the explicit nesting. It makes the code feeling complicate. It often don’t fits in the frame of 80 chars per line :-(.
Today I’ve put together a small helper class that collects calls and executes them by chaining them as callbacks.
var devcoach = devcoach || {};
devcoach.CallChain = function () {
var cs = [];
this.add = function (call) {
cs.push(call);
};
this.execute = function () {
var wrap = function (call, callback) {
return function () {
call(callback);
};
};
for (var i = cs.length-1; i > -1; i--) {
cs[i] =
wrap(
cs[i],
i < cs.length - 1
? cs[i + 1]
: null);
}
cs[0]();
};
};
This few lines now let you write a more clear and easy to read calls automatically being nested calling the follower as callback.
var cc = new devcoach.CallChain();
cc.add(f1);
cc.add(f2);
cc.add(f3);
cc.execute();