varias llamadas ajax esperan a que se cargue la última, luego se ejecutan

Tengo varias consultas ajax ejecutándose al mismo tiempo, y quiero que esperen a que regrese la última, y ​​luego ejecutar el controlador de éxito en todas las llamadas ajax. Para un ejemplo simplificado, considere:

$.ajax({//ajax call 1 url:page1.php, success: function(data1){ //do something with data1 } }); .... $.ajax({//ajax call 2 url:page2.php, success: function(data2){ //do something with data2 } }); //consider more than just two concurrent requests 

Digamos que todas las solicitudes se envían al mismo tiempo. Como son asíncronos, volverán en diferentes momentos. Digamos que una solicitud tarda 100 ms en volver y la otra solicitud tarda 3000 ms en volver. Obviamente no sé cuál regresará primero o último. Todos ellos actualizan el DOM de alguna manera y quiero que todos los cambios se muestren al espectador al mismo tiempo en una actualización. ¿Cómo hago esto?

Lo mejor que puedo pensar es guardar data1 y data2 como variables globales. Y luego tenga una variable de contador que cuente cada vez que se devuelva un éxito. Luego, en el contador == TOTAL_NUM_REQUESTS llama a una función como updateAll (), luego ejecuta todas las variables globales y las coloca donde deben ir. Pero esto parece desordenado y propenso a errores. Además, eso sería una gran cantidad de variables globales.

Lo que idealmente quiero es que los manejadores de éxitos duerman al regresar, y luego de mi condición de contarlos como devueltos, enviar mensajes de activación a todos ellos y pueden reanudar la ejecución. Esto parece lo más limpio, pero no conozco ninguna funcionalidad como esta en javascriptland.

¿Alguien tiene alguna idea ingeniosa para esto?

RESPUESTA ACTUALIZADA

Gracias a Lee a continuación, pude obtener una solución. Mi solución se parecía a la de abajo. Construyo una lista de variables async que fueron asignadas a la llamada $ .ajax. Inicialmente, el controlador de éxito de esas llamadas ajax todavía se estaba llamando, así que las eliminé y las puse en otra función que se llamaría posteriormente when escribí el bloque. Pasé los results a la función como esta:

 var results = []; results.push(async1); results.push(async2); ... for all the results ... $.when.apply(this, results).done(function() { for(var i=0;i<arguments.length;i++){ dataobject=arguments[i][0] if(dataobject.variousattribute) mySuccessHandlerFirstGuy(dataobject) else if(dataobject.anotherattribute) mySuccessHandlerSecondGuy(dataobject) //etc .... } }; 

Los argumentos objeto tuvieron un poco de trabajo para averiguar lo que era. Era una matriz 2d (lista de listas). El primer índice representó el objeto devuelto correspondiente a una solicitud ajax dada. Parece estar en orden, pero sería mejor que su servidor devuelva algo que pueda buscar y escriba un bloque if / else en consecuencia. Luego, en ese elemento dado, parece haber 3 elementos dentro de esa lista. El primero es el valor que se devolvió del servidor, es decir, lo que desea. El segundo siempre fue un success cadena, que presumiblemente puede usar para verificar si la llamada funcionó. Y el tercer elemento en esa lista parece ser la solicitud inicial (aunque no estoy seguro). Esto no me sirvió de nada.

De todos modos, espero que esto ayude a alguien en el futuro. Y gracias de nuevo a Lee por apuntarme en la dirección correcta.

Use la función jQuery $ .when () para ejecutar algo cuando todas las llamadas ajax terminen:

jQuery.when docs

 var async1 = $.ajax({//ajax call 1 url:page1.php, success: function(data1){ //do something with data1 } }); .... var async2 = $.ajax({//ajax call 2 url:page2.php, success: function(data2){ //do something with data2 } }); $.when(async2, async1).done(function(result2, result1) { ... do this when both are successful ... }); 

Añadido en respuesta a las preguntas:

Si tiene un montón de llamadas ajax, puede usar ‘aplicar’ de la siguiente manera:

 var results = []; results.push(async1); results.push(async2); ... for all the results ... $.when.apply(this, results).done(function() { ... use 'arguments' array to get results ... }); 

Esto probablemente se puede hacer de una manera muy similar a lo que ya ha propuesto.

Primero, cree variables globales var sleep = true y var request_count = 0 . Luego, inicie un temporizador que verifique request_count contra el número total de solicitudes cada segundo aproximadamente. Luego, sus funciones de éxito pueden incrementar request_counter y luego comenzar a hacer bucles hasta que sleep == false . Luego, cuando la función de supervisión que se ejecuta a través del temporizador detecta request_count == TOTAL_REQUESTS , establece sleep = false , y todas las funciones de éxito continúan en su negocio en ese momento.

Una solución simple será utilizar el módulo PreloaderQ.

https://www.npmjs.com/package/preloaderq

Usar como abajo

 var preloader = new PreloaderQ() preloader.setEmptyCallback(function(){ //all tasks are finished }) preloader.setFirstTaskCallback(function(){ //started first task }) preloader.enqueueTask('ajax1') $.ajax({//ajax call 1 url:page1.php, success: function(data1){ prealoader.dequeueTask('ajax1') //do something with data1 } }); preloader.enqueueTask('ajax2') $.ajax({//ajax call 1 url:page2.php, success: function(data2){ prealoader.dequeueTask('ajax2') //do something with data2 } }); 

La llamada vacía se llamará después de que ambos hayan terminado