I see that c doesn't depend of b result, and b doesn't depend of a result.
Following the GRASP principles (http://en.wikipedia.org/wiki/GRASP_(object-oriented_design), a mustn't know b and b mustn't know c.
When we program, to remember the GRASP principles or guidelines is very important.
High Cohesion and Low Coupling mean that our code will be better, more reusable and easier to maintain.
The main function which knows a, b, and c must build the chained calls.
The functions would be:
function a(param1, param2) {
var deferred = $.Deferred();
console.log(" function a: begin. Params " + param1 + " and " + param2);
mockPost("a_url").done(function() {
console.log(" function a: end ok. Params " + param1 + " and " + param2);
deferred.resolve();
}).fail(function() {
console.log(" function a: end fail. Params " + param1 + " and " + param2);
deferred.reject();
});
return deferred.promise();
}
function b() {
var deferred = $.Deferred();
console.log(" function b: begin");
mockPost("b_url").done(function() {
console.log(" function b: end ok.");
deferred.resolve();
}).fail(function() {
console.log(" function b: end fail.");
deferred.reject();
});
return deferred.promise();
}
function c() {
// We suppose that c function calls to post function and anything more
return mockPost("c_url");
}
The main function would be:
// Array with params for a function (a function is the first link in chain)
var data = [{param1 : 1235, param2: 3214}, {param1 : 5432, param2: 9876}];
// Array with calls to each fixed sequence a, b, and c. We iterate over data array
var arrayFunctions = [];
$.each(data, function(i,obj) {
arrayFunctions.push(
function() {
console.log("Params in data with index " + i + ":");
// We define the fixed sequence: a with params, b without params and c without params
return $.iterativeWhen(
function() {
return a(obj.param1, obj.param2);
},
b,
c
);
}
)
});
// Start the global process
$.iterativeWhen.apply($, arrayFunctions)
.done(function() {
console.log ("----------------");
console.log ("> Global Success");
})
.fail(function() {
console.log ("--------------");
console.log ("> Global Fail");
});
$.iterativeWhen doesn't exist in jQuery, so I have built it. It works with jQuery 1.8 and later versions.
$.iterativeWhen = function () {
var deferred = $.Deferred();
var promise = deferred.promise();
$.each(arguments, function(i, obj) {
promise = promise.then(function() {
return obj();
});
});
deferred.resolve();
return promise;
};
The mockPost function simulates a call to $.post with a success probability:
function mockPost(url) {
var deferred = $.Deferred();
setTimeout(function() {
if (Math.random() <= 0.9) {
console.log(" request url: " + url + "... ok");
deferred.resolve();
} else {
console.log(" request url: " + url + "... fail");
deferred.reject();
}
}, 1000);
return deferred.promise();
}
The log output is:
Params in data with index 0:
function a: begin. Params 1235 and 3214
request url: a_url... ok
function a: end ok. Params 1235 and 3214
function b: begin
request url: b_url... ok
function b: end ok.
request url: c_url... ok
Params in data with index 1:
function a: begin. Params 5432 and 9876
request url: a_url... ok
function a: end ok. Params 5432 and 9876
function b: begin
request url: b_url... ok
function b: end ok.
request url: c_url... ok
----------------
> Global Success
jsFiddle here: http://jsfiddle.net/E2tp3/