There are many ways to write this kind of thing.
A flexible approach is separate “actions” from “sequence”, allowing :
- functions a, b, c to initiate an asynchronous (ajax) action, with no knowledge of how they are to be sequenced
- a, b, c to be reusable, as part of one or more sequences or individually, as required.
Here’s a way to code this approach, using .then()
exclusively for the chaining logic :
function a() {
return $.post(...).then(function(result) {
if(result)
return result;//continue on "success" path.
else
return $.Deferred().reject('a').promise();//convert success to failure.
}, function() {
return 'a';//continue on failure path.
});
}
function b() {
return $.post(...).then(function(result) {
if(result)
return result;//continue on "success" path.
else
return $.Deferred().reject('b').promise();//convert success to failure.
}, function() {
return 'b';//continue on failure path.
});
}
function c() {
return $.post(...).then(function(result) {
if(result)
return result;//continue on "success" path.
else
return $.Deferred().reject('c').promise();//convert success to failure.
}, function() {
return 'c';//continue on failure path.
});
}
a().then(b).then(c).then(function() {
console.log("successful");
}, function(id) {
console.log("failed: " + id);
});
Alternatively, if you want to have a single asynchronous function, a
, called from within a loop then the code could be something like this :
function a(obj) {
return $.post(...).then(function(result) {
if(result)
return result;//continue on "success" path.
else
return $.Deferred().reject(obj.id).promise();//convert success to failure.
}, function() {
return obj.id;//continue on failure path.
});
}
var data = [{id:'A', param1:1235, param2:3214}, {id:'B', param1:5432, param2:9876}];
//Note how IDs are included so these data objects can be identified later in failure cases.
var dfrd = $.Deferred();//starter Deferred for later resolution.
var p = dfrd.promise();//A promise derived from the starter Deferred, forming the basis of a .then() chain.
//Build a .then() chain by assignment
$.each(data, function(i, obj) {
p = p.then( function() {
return a(obj);
});//By not including a fail handler here, failures will pass straight through to be handled by the terminal .then()'s fail handler.
});
//Chain a terminal .then(), with success and fail handlers.
p.then(function() {
console.log("successful");
}, function(id) {
console.log("failed: " + id);
});
dfrd.resolve();//Resolve the starter Deferred to get things started.