Supongamos que tienes varias peticiones ajax y deseas disparar un evento solo cuando todas ellas se completen. ¿Existe algun modo elegante en JQuery de hacer esto?
-
Hola Bienvenido a [es.SO], te invito a hacer el [tour] y también a que leas [ask], por otro lado tu pregunta puede considerarse de baja calidad o basada en opiniones, orientándote a lo que solicitas, revisa esta pregunta de promesas [¿Qué es una promesa en Javascript?](https://es.stackoverflow.com/q/64265/6635) – JuankGlezz Jun 06 '17 at 17:22
-
Pues lo que se me ocurre es que las vayas anidando una dentro de la otra para que cuando llegue a la ultima dispare el evento que comentas, porque de otro modo si disparas todas y sin asincronas no todos terminan al mismo tiempo. – M. Gress Jun 06 '17 at 17:03
2 Answers
si, lo que estas buscando es Promesas
Qué son las promesas?
El objeto Promise (Promesa) es usado para computaciones asíncronas. Una promesa representa un valor que puede estar disponible ahora, en el futuro, o nunca.
Fuente: ¿Qué es una promesa en Javascript?
Un llamado a ajax entonces no es una promesa?
Claro, por eso podes hacer
$.ajax({
url: "http://algunsitio.com/datos.php",
})
.done(function( data ) {
if ( console && console.log ) {
console.log( "Sample of data:", data.slice( 0, 100 ) );
}
});
.done se ejecuta recién cuando ajax devuelve los datos, entonces, para ejecutar lo que necesitas podes hacer
$.ajax(...)
.done(function(data) {
$.ajax(...)
.done(..)
});
lo cual no es aconsejable, porque es poco legible.
Al rescate, jquery when
http://api.jquery.com/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,
...
});
}
( respuesta sacada de esta gran respuesta de otro usuario en ingles: https://stackoverflow.com/questions/3709597/wait-until-all-jquery-ajax-requests-are-done )
Alternativa:
Otro método común en angular es usar la libreria Q y hacer Q.all
liberia Q: http://documentup.com/kriskowal/q/
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();
});
Pero leí por ahí que a veces Q.all no funciona correctamente.
También podrías volverte creativo y hacer que cada promesa ejecute un código y a su vez llene una 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.
}
- 625
- 5
- 11
La solución más simple que se me ocurre es usar 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
});
- 538
- 2
- 8