I have 3 processes that needs ajax to complete. But it is asynchronous and it fails to do what I wanted to do..
Lets say:
function a(param1, param2) {
$.post(..., function(result){
if(result){
b();
} else {
console.log("failed a");
}
})
}
function b() {
$.post(..., function(result){
if(result){
c();
} else {
console.log("failed b");
}
})
}
function c() {
$.post(..., function(result){
if(result){
console.log("successful");
} else {
console.log("failed b");
}
})
}
I want it to execute like this
a
b
c
That code will work perfectly, as you can see.. but if use a loop.
var data = [{param1 : 1235, param2: 3214}, {param1 : 5432, param2: 9876}];
$.each(data, function(k,v){
a(v.param1, v.param2)
});
It will not work as expected and will just do:
a
a
b
b
c
c
instead of
a
b
c
a
b
c
There are many ways to write this kind of thing.
A flexible approach is separate "actions" from "sequence", allowing :
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.
You can chain asynchronous calls like ajax calls using jQuery's deferred object and using 'then'.
You can also change it to use functions that returns a deferred promise object, instead of an ajax call as I have in my example.
http://jsfiddle.net/q4cFv/
(Example with async function: http://jsfiddle.net/q4cFv/1/)
$(function() {
var delay = 3,
span = $('span'),
posts = [
{
input1: 'My name 1',
input2: 'My address 1',
input3: 'My country 1'
},
{
input1: 'My name 2',
input2: 'My address 2',
input3: 'My country 2'
},
{
input1: 'My name 3',
input2: 'My address 3',
input3: 'My country 3'
},
{
input1: 'My name 4',
input2: 'My address 4',
input3: 'My country 4'
}
],
looper = $.Deferred().resolve();
$.each(posts, function(i, data) {
looper = looper.then(function() {
return $.ajax({
data: {
json: JSON.stringify(data),
delay: delay
},
method: 'post',
url: '/echo/json/',
dataType: 'json'
}).done(function(response) {
span.append('Response:<br />');
for(key in response) {
span.append(key + ': ' + response[key] + '<br />');
}
$('span').append('Waiting ' + delay + ' seconds<br /><br />');
});
});
});
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With