Suppose you have several ajax requests and you want to trigger an event only when all of them are completed. Is there any elegant way in JQuery to do this?
Suppose you have several ajax requests and you want to trigger an event only when all of them are completed. Is there any elegant way in JQuery to do this?
Yes, what you are looking for is Promises
What are the promises?
The Promise object is used for asynchronous computations. A promise represents a value that may be available now, in the future, or never.
Source: What is a promise in Javascript? ?
A call to ajax then is not a promise?
Sure, that's why you can do
$.ajax({
url: "http://algunsitio.com/datos.php",
})
.done(function( data ) {
if ( console && console.log ) {
console.log( "Sample of data:", data.slice( 0, 100 ) );
}
});
.done is just executed when ajax returns the data, so, to execute what you need you can do
$.ajax(...)
.done(function(data) {
$.ajax(...)
.done(..)
});
which is not advisable, because it is not readable.
To the rescue, jquery when
$.when(ajax1(), ajax2(), ajax3(), ajax4()).done(function(a1, a2, a3, a4){
// el codigo aqui se ejecuta una vez que las cuatro promesas se
// resolvieron
});
function ajax1() {
// NOTE: esta funcion debe retornar el resultado
// del metodo $.ajax(),el cual es una promesa.
return $.ajax({
url: "someUrl",
dataType: "json",
data: yourJsonData,
...
});
}
(response taken from this great response from another user in English: link )
Alternative:
Another common method in angular is to use the Q library and make Q.all
liberia Q: link
let promises = [promiseAlpha(), promiseBeta(), promiseGamma()];
$q.all(promises).then((values) => {
console.log(values[0]); // value alpha
console.log(values[1]); // value beta
console.log(values[2]); // value gamma
complete();
});
But I read that sometimes Q.all does not work correctly.
You could also become creative and have each promise execute a code and in turn fill in a variable
var promisesFulfilled = [0,0,0,0];
function promise0() {
$.ajax({
url: "http://algunsitio.com/datos.php",
})
.done(function( data ) {
promisesFulfilled[0] = 1;
checkPromises();
});
}
function checkPromises() {
//si promisesFulfilled tiene todos 1, ya se terminaron las 4.
}
The simplest solution I can think of is to use Deferreds
$.when(
// Tambien funciona con get y post
$.ajax("/primera"),
$.ajax("/segunda"),
$.ajax("/tercera")
)
.done(function(primero, segundo, tercero){
// lo que quieras cuando funcione
})
.fail(function(){
//lo que quieras cuando fallen
});