2011-11-11 32 views
5

Estoy usando jQuery y tengo un bucle de solicitudes AJAX asincrónicas. Sé que puedo esperar a que todos terminen usando el práctico método '$ .when.apply (array_of_requests) .then()'.Cómo esperar hasta que las solicitudes async jQuery AJAX anidadas hayan finalizado?

Pero también tengo otro conjunto de solicitudes AJAX que solo se ejecutan después de finalizar cada una de las primeras solicitudes. Quiero esperar a que terminen también, pero no estoy 100% seguro de haber encontrado la mejor manera.

Aquí está un ejemplo simplificado de mis solicitudes:

var intital_data = [1,2,3,4,5,6,7,8,9,10]; 
var promises = []; 
var promises_inner = []; 

$.each(intitial_data, function(i, n) { 
    var ajax_call = $.ajax({url:'http://www.domain.com/etc/'+n}); 
    promises.push(ajax_call); 

    ajax_call.done(function(data) { 
     var ajax_call_inner = $.ajax({url:'http://www.domain.com/etc/'+data.result}); 
     promises_inner.push(ajax_call_inner); 

     ajax_call_inner.done(function(data) { 
      // Do something with the content of data here. 
     }); 
    }); 
}); 

Así, cuando cada uno de los diez bucle peticiones AJAX se hace, puedo hacer una segunda petición AJAX basado en los resultados de la primera. Eso todo funciona bien.

que luego tienen algo como esto, porque quiero esperar a que tanto los primeros diez solicitudes (almacenado en la matriz promesas) y el segundo lote (almacenado en promises_inner) se completan:

$.when.apply($, promises).then(
    function() { 
     // The ten outer AJAX calls are finished now. 

     $.when.apply($, promises_inner).then(
      function() { 
       // The inner AJAX calls are finished now. 
      } 
     ); 
    } 
); 

Dentro de la primera función 'done' de $ .when.apply(). Then(), el segundo lote de solicitudes aún no se ha completado, o incluso se ha agregado a la matriz promises_inner. Pero descubrí que la adición de un $ .when.apply(). Then() parece funcionar: dentro de su función 'hecha' todos las solicitudes han finalizado.

Pero no estoy seguro de que esta sea la mejor y más robusta solución. Me preocupa que solo funcione casualmente, que esté causando la demora suficiente para que las llamadas hayan terminado, en lugar de tener un sentido lógico.

¿Existe una solución mejor y más sólida? Gracias.

+0

hablé demasiado pronto cuando dije que parece que funciona. a veces funciona, pero otras veces, promises_inner no ha tenido toda la anuncio de consultas AJAX anidado dedicado a ello todavía Entonces, a veces el $ interno ocurre cuando todo ha sido devuelto. –

Respuesta

2

Eche un vistazo a $ .Callbacks in 1.7. Creo que estará entusiasmado con la flexibilidad de hacer sus propios "flujos" y la capacidad de reutilizarlos, ejecutarlos una vez, etc.

No hay nada de malo con lo que hizo (el patrón de aplicación puede no ser una primera opción de la mayoría, por lo general solo los enumeran en un $ .when (a, b, c ....) - pero es posible que le guste la sintaxis de $ .Callbacks.

+0

Gracias por el puntero. ¡Los documentos de $ .Callbacks están lastimando mi cerebro, pero espero que finalmente se hunda! Mientras tanto, ¿crees que mi $ anidado $ .when ... s debería ser confiable? –

+0

Tenemos que hacer cosas similares cuando procesamos las reglas en nuestra aplicación de seguro porque hay al menos 10 servicios involucrados. La otra cosa que puede hacer y que puede ser más fácil de leer es crear un aplazado y solo resolverlo cuando termine el primero. Use la promesa de Deferred como el .done para el próximo conjunto de devoluciones de llamada. Addy Osmani tiene un buen artículo sobre Callbacks y es probable que vengan más. – AutoSponge

0

Pruebe esto con una sola promesa principal de fullfill (resolver) por lazo de gestión (aquí todavía se llama inner_promise).

var initial_data = [1,2,3,4,5,6,7,8,9,10]; 
var promises_inner = []; 

initial_data.forEach(function(n) { 
    // Create promise for the inner call here. 
    var promise_inner = $.Deferred(); 
    promises_inner.push(promise_inner); 

    $.ajax({url:'http://www.domain.com/etc/'+n}).done(function(data) { 
     $.ajax({url:'http://www.domain.com/etc/'+data.result}).done(function(data) { 
      // Do something with the content of data here. 
      promise_inner.resolve(); 
     }); 
    }); 
}); 
console.log("promises_inner contains " + promises_inner.length + " promises") // should contain all the 10 promises 

$.when.apply($,promises_inner).done(function() { 
    // The inner AJAX calls are finished now 
}) 
Cuestiones relacionadas