¿Esperar hasta que se completen todas las solicitudes de jQuery Ajax?

675

¿Cómo hago que una función espere hasta que todas las solicitudes de jQuery Ajax se realicen dentro de otra función?

En resumen, necesito esperar a que se realicen todas las solicitudes de Ajax antes de ejecutar la siguiente. ¿Pero cómo?

jamietelin
fuente
¿Cómo estás llamando a tus solicitudes ajax originales?
NakedBrunch
2
¿Qué quieres decir con "hecho"? Lo entiendo como "todas las solicitudes han finalizado con éxito o no" (resuelto o rechazado). Pero puede querer decir "todas las solicitudes han finalizado correctamente" (resuelto). ver todas las variaciones en api.jquery.com/category/deferred-object
Adrien Be

Respuestas:

911

jQuery ahora define una función when para este propósito.

Acepta cualquier cantidad de objetos diferidos como argumentos y ejecuta una función cuando todos se resuelven.

Eso significa que, si desea iniciar (por ejemplo) cuatro solicitudes de ajax, luego realizar una acción cuando terminen, podría hacer algo como esto:

$.when(ajax1(), ajax2(), ajax3(), ajax4()).done(function(a1, a2, a3, a4){
    // the code here will be executed when all four ajax requests resolve.
    // a1, a2, a3 and a4 are lists of length 3 containing the response text,
    // status, and jqXHR object for each of the four ajax calls respectively.
});

function ajax1() {
    // NOTE:  This function must return the value 
    //        from calling the $.ajax() method.
    return $.ajax({
        url: "someUrl",
        dataType: "json",
        data:  yourJsonData,            
        ...
    });
}

En mi opinión, crea una sintaxis limpia y clara, y evita la participación de variables globales como ajaxStart y ajaxStop, que podrían tener efectos secundarios no deseados a medida que se desarrolla su página.

Si no sabe de antemano cuántos argumentos de ajax necesita esperar (es decir, si desea usar un número variable de argumentos), aún puede hacerse, pero es un poco más complicado. Consulte Pasar en una matriz de diferidos a $ .when () (y tal vez jQuery. Al solucionar problemas con un número variable de argumentos ).

Si necesita un control más profundo sobre los modos de falla de los scripts ajax, etc., puede guardar el objeto devuelto por .when(): es un objeto jQuery Promise que abarca todas las consultas ajax originales. Puede invocarlo .then()o .fail()agregarlo para agregar controladores detallados de éxito / falla.

Alex
fuente
46
Esto debe marcarse como una respuesta correcta porque es simple, eficiente y funciona muy bien. Además, debe tenerse en cuenta que $.whendevuelve un Promiseobjeto que tiene métodos más útiles, no solo .done. Por ejemplo, con el .then(onSuccess, onFailure)método podría reaccionar cuando ambas solicitudes tengan éxito o al menos una de ellas falle.
skalee
2
¿Es posible agrupar las solicitudes ajax1..4 en una matriz y pasar eso?
andig
33
Ten cuidado con el failcaso. A diferencia done, faildispara inmediatamente en el primer fallo e ignora los aplazamientos restantes.
Ryan Mohr
1
@skalee, gracias por resaltar el hecho de que onFailurese puede adjuntar una función. Como señalé en un comentario a la pregunta del OP: podría querer indicar con mayor precisión lo que quería decir con "hecho". "Ryan Mohr" también tuvo un muy buen punto con respecto al hecho de que se failcomporta de manera diferente done, ya Promisesque creo que hay que leer más sobre html5rocks.com/en/tutorials/es6/promises
Adrien Be
1
Es genial dar a las personas exposición al método when y a las promesas en general, pero creo que esta no es la mejor respuesta. Si alguna de esas funciones ajax en algún punto de la línea crea otra solicitud ajax, y luego no integra esa nueva promesa correctamente en la cadena ... esas solicitudes escaparán de esta técnica. Por ejemplo, no puedo usar esta técnica sin modificar la biblioteca de Shopify que estoy usando para el comportamiento de agregar a la cesta de ajax, porque no se escribió de manera 'promisoria' y nunca devuelve los objetos xhr que crea. ¿Esto tiene sentido? Sin embargo, sigue siendo una gran respuesta.
Ziggy
292

Si desea saber cuándo ajax finalizan todas las solicitudes en su documento, no importa cuántas existan, simplemente use el evento $ .ajaxStop de esta manera:

$(document).ajaxStop(function () {
  // 0 === $.active
});

En este caso, no necesita adivinar cuántas solicitudes están ocurriendo en la aplicación, que podrían terminar en el futuro, ni profundizar en la lógica compleja de las funciones o encontrar qué funciones están haciendo HTTP(S)solicitudes.

$.ajaxStopaquí también puede vincularse a cualquier HTMLnodo que creas que podría ser modificado por requst.


Actualización:
si desea seguir con la ESsintaxis, puede usar Promise.all para ajaxmétodos conocidos :

Promise.all([ajax1(), ajax2()]).then(() => {
  // all requests finished successfully
}).catch(() => {
  // all requests finished but one or more failed
})

Un punto interesante aquí es que funciona con Promisesy con $.ajaxsolicitudes.

Aquí está la demostración de jsFiddle .


Actualización 2:
Sin embargo, una versión más reciente que utiliza la sintaxis async / await :

try {
  const results = await Promise.all([ajax1(), ajax2()])
  // do other actions
} catch(ex) { }
Arsen Khachaturyan
fuente
16
+1 Mucho mejor que otras respuestas en caso de que tenga que lidiar con scripts de terceros con devoluciones / cierres de llamadas anónimos.
Kaiser
55
@kaiser Punto válido pero no es lo que la pregunta estaba haciendo. No es muy bueno si no quieres esperar a que vuelvan todas las llamadas AJAX. La pregunta es específica acerca de esperar las llamadas AJAX que ha realizado por su cuenta (llamada dentro de otra función, como escribió el OP). Es posible que otro código haya realizado otra llamada AJAX que no desea esperar.
Juan Mendes
66
En comparación con la solución when (), tiene la ventaja de funcionar incluso si no se conoce el número de llamadas ajax.
Alexis Dufrenoy
55
En comparación con la solución when (), tiene la gran desventaja de no funcionar bien junto con otros componentes, ya que comparte un estado global de todo el documento. Si hay una larga encuesta continua, incluso puede que nunca se active.
Bergi
3
No estás correcto @AdrienBe, ajaxStop maneja todas las solicitudes de ajax sin importar si tienen éxito o no, solo como prueba de mis palabras mira este jsfiddle.net/36votxba/2
Arsen Khachaturyan
32

He encontrado una buena respuesta por gnarf mi mismo que es exactamente lo que estaba buscando :)

jQuery ajaxQueue

//This handles the queues    
(function($) {

  var ajaxQueue = $({});

  $.ajaxQueue = function(ajaxOpts) {

    var oldComplete = ajaxOpts.complete;

    ajaxQueue.queue(function(next) {

      ajaxOpts.complete = function() {
        if (oldComplete) oldComplete.apply(this, arguments);

        next();
      };

      $.ajax(ajaxOpts);
    });
  };

})(jQuery);

Luego puede agregar una solicitud ajax a la cola de esta manera:

$.ajaxQueue({
        url: 'page.php',
        data: {id: 1},
        type: 'POST',
        success: function(data) {
            $('#status').html(data);
        }
    });
jamietelin
fuente
37
Parece que has olvidado dar la atribución adecuada a esta respuesta , la he agregado.
Tim Post
21

Usa el ajaxStopevento.

Por ejemplo, supongamos que tiene un mensaje de carga ... mientras recupera 100 solicitudes ajax y desea ocultar ese mensaje una vez cargado.

Del documento jQuery :

$("#loading").ajaxStop(function() {
  $(this).hide();
});

Tenga en cuenta que esperará a que se realicen todas las solicitudes de ajax en esa página.

olafure
fuente
55
Esto supone que usted sabe que no habrá otras solicitudes AJAX en la página, no es una muy buena suposición
Juan Mendes
A partir de jQuery 1.8, el método .ajaxStop () solo debe adjuntarse al documento.
Geomorillo
1
Corríjame si me equivoco, pero ¿esto no convertirá su proyecto en un sitio de "formularios web de la vieja escuela"? Quiero decir, si toda su página tiene que esperar una solicitud antes de que pueda continuar, ¿cuál es el punto de la solicitud ajax en primer lugar?
BillRuhl
@BillRuhl en nuestro caso, estoy recorriendo una colección de jquery para crear cosas nuevas y necesito saber sobre toda la colección cuando esté lista, antes de hacer algunos ajustes de diseño. No parece un caso particularmente inusual. Sería malo si un montón de otras cosas de ajax pudieran estar en proceso, pero no lo será, aquí.
eon
21

NOTA: Las respuestas anteriores utilizan una funcionalidad que no existía en el momento en que se escribió esta respuesta. Recomiendo usar en jQuery.when()lugar de estos enfoques, pero estoy dejando la respuesta con fines históricos.

-

Probablemente podría sobrevivir con un simple semáforo de conteo, aunque la forma en que lo implemente dependerá de su código. Un ejemplo simple sería algo así como ...

var semaphore  = 0,     // counting semaphore for ajax requests
    all_queued = false; // bool indicator to account for instances where the first request might finish before the second even starts

semaphore++;
$.get('ajax/test1.html', function(data) {
    semaphore--;
    if (all_queued && semaphore === 0) {
        // process your custom stuff here
    }
});

semaphore++;
$.get('ajax/test2.html', function(data) {
    semaphore--;
    if (all_queued && semaphore === 0) {
        // process your custom stuff here
    }
});

semaphore++;
$.get('ajax/test3.html', function(data) {
    semaphore--;
    if (all_queued && semaphore === 0) {
        // process your custom stuff here
    }
});

semaphore++;
$.get('ajax/test4.html', function(data) {
    semaphore--;
    if (all_queued && semaphore === 0) {
        // process your custom stuff here
    }
});

// now that all ajax requests are queued up, switch the bool to indicate it
all_queued = true;

Si desea que esto funcione como {async: false} pero no desea bloquear el navegador, puede lograr lo mismo con una cola jQuery.

var $queue = $("<div/>");
$queue.queue(function(){
    $.get('ajax/test1.html', function(data) {
        $queue.dequeue();
    });
}).queue(function(){
    $.get('ajax/test2.html', function(data) {
        $queue.dequeue();
    });
}).queue(function(){
    $.get('ajax/test3.html', function(data) {
        $queue.dequeue();
    });
}).queue(function(){
    $.get('ajax/test4.html', function(data) {
        $queue.dequeue();
    });
});
BBonifield
fuente
10
Esto parece complicar demasiado un problema trivial.
Chris
2
Realmente no es tan complicado. El recuento de semáforos es un mecanismo común en CS. Sin embargo, si lo prefiere, el ejemplo usando colas jQuery funcionaría también sin tener que implementar el semáforo usted mismo.
BBonifield
1
No veo un problema con el contador de semáforos, sin embargo, sí veo un problema con la idea de tener CUATRO funciones para manejar la devolución de llamada resultante. Primero debe definir una función, luego hacer referencia a esa función en cada una .get(). De esa manera al menos no duplicas ese código. ¡No solo eso, sino que declarando a function(){}cada vez asigna memoria cada vez! Más bien una mala práctica si pudieras llamar a una función estáticamente definida.
Alexis Wilke
1
@AlexisWilke Esta es una respuesta de 4.5 años de antigüedad, y fue un ejemplo de cómo funcionan los semáforos y las colas. Estás pensando demasiado en esto, y no creo que sea necesaria la CAPITALIZACIÓN PARA HACER UN PUNTO.
BBonifield
2
Bueno ... no fui yo quien te dio un -1 ... y entiendo que las respuestas tienden a envejecer. Sin embargo, la gente sigue encontrándolos y, hasta donde yo sé, no está prohibido dar información a las personas que podrían hacer uso de ellos aún hoy.
Alexis Wilke el
8

JavaScript está basado en eventos, por lo que nunca debe esperar , en lugar de establecer ganchos / devoluciones de llamada

Probablemente solo pueda usar los métodos de éxito / completo de jquery.ajax

O podría usar .ajaxComplete :

$('.log').ajaxComplete(function(e, xhr, settings) {
  if (settings.url == 'ajax/test.html') {
    $(this).text('Triggered ajaxComplete handler.');
    //and you can do whatever other processing here, including calling another function...
  }
});

aunque debe publicar un pseudocódigo de cómo se llama (s) su (s) solicitud (es) ajax para ser más precisos ...

Stefano
fuente
8

Una pequeña solución es algo como esto:

// Define how many Ajax calls must be done
var ajaxCalls = 3;
var counter = 0;
var ajaxCallComplete = function() {
    counter++;
    if( counter >= ajaxCalls ) {
            // When all ajax calls has been done
        // Do something like hide waiting images, or any else function call
        $('*').css('cursor', 'auto');
    }
};

var loadPersons = function() {
        // Show waiting image, or something else
    $('*').css('cursor', 'wait');

    var url = global.ctx + '/loadPersons';
    $.getJSON(url, function(data) {
            // Fun things
    })
    .complete(function() { **ajaxCallComplete();** });
};

var loadCountries = function() {
    // Do things
    var url = global.ctx + '/loadCountries';
    $.getJSON(url, function(data) {
            // Travels
    })
    .complete(function() { **ajaxCallComplete();** });
};

var loadCities = function() {
    // Do things
    var url = global.ctx + '/loadCities';
    $.getJSON(url, function(data) {
            // Travels
    })
    .complete(function() { **ajaxCallComplete();** });
};

$(document).ready(function(){
    loadPersons();
    loadCountries();
    loadCities();
});

La esperanza puede ser útil ...

Jesfre
fuente
Si bien las otras respuestas son técnicamente mejores, ya que es mucho más fácil de entender, realmente me gusta esta. ¡Agradable!
Jay
4

jQuery le permite especificar si desea que la solicitud ajax sea asíncrona o no. Simplemente puede hacer que las solicitudes ajax sean síncronas y luego el resto del código no se ejecutará hasta que regresen.

Por ejemplo:

jQuery.ajax({ 
    async: false,
    //code
});
shmuel613
fuente
42
Una cosa a tener en cuenta es que el uso de {async: false} puede bloquear temporalmente el navegador. api.jquery.com/jQuery.ajax
BBonifield
30
Esto es contrario a la práctica estándar de jQuery / Javascript. Se supone que AJAX siempre es asíncrono. Debería usar jQuery.when () en su lugar.
SystemParadox
43
¡Es una idea terriblemente mala! ¡Nunca hagas eso! Bloqueo = ¡no responde a las acciones del usuario, ni siquiera al desplazamiento ni nada! (Además, async: false será obsoleto en jQuery 1.8.)
skalee
55
Particularmente si la solicitud falla o toma mucho tiempo por alguna razón impredecible (que, según la ley de Murphy, ¡sucederá!), Esta es generalmente una mala idea para el código de producción debido al bloqueo del navegador como se indicó anteriormente.
Alex
27
Esta es una idea horriblemente mala. NO UTILICE ESTA RESPUESTA.
Tauren
2

Si necesitas algo simple; devolución de llamada una vez y hecho

        //multiple ajax calls above
        var callback = function () {
            if ($.active !== 0) {
                setTimeout(callback, '500');
                return;
            }
            //whatever you need to do here
            //...
        };
        callback();
Fatmuemoo
fuente
44
¡puede generar un bucle sin fin!
Diego Favero
2
Este es un bucle sin fin? ¿Cuando? Cuando el AJAX nunca regresa?
Jonathan
2

También podría usar async.js .

Creo que es mejor que $ .when porque puedes combinar todo tipo de llamadas asincrónicas que no admiten promesas listas para usar, como tiempos de espera, llamadas SqlLite, etc., y no solo solicitudes ajax.

George Mavritsakis
fuente
2

Sobre la base de la respuesta @BBonifield, escribí una función de utilidad para que la lógica del semáforo no se extienda en todas las llamadas ajax.

untilAjax es la función de utilidad que invoca una función de devolución de llamada cuando se completan todas las llamadas ajax.

ajaxObjses una matriz de objetos de configuración ajax [http://api.jquery.com/jQuery.ajax/].

fn es la función de devolución de llamada

function untilAjax(ajaxObjs, fn) {
  if (!ajaxObjs || !fn) {
    return;
  }
  var ajaxCount = ajaxObjs.length,
    succ = null;

  for (var i = 0; i < ajaxObjs.length; i++) { //append logic to invoke callback function once all the ajax calls are completed, in success handler.
    succ = ajaxObjs[i]['success'];
    ajaxObjs[i]['success'] = function(data) { //modified success handler
      if (succ) {
        succ(data);
      }
      ajaxCount--;
      if (ajaxCount == 0) {
        fn(); //modify statement suitably if you want 'this' keyword to refer to another object
      }
    };
    $.ajax(ajaxObjs[i]); //make ajax call
    succ = null;
  };

Ejemplo: doSomethingusos de funciones untilAjax.

function doSomething() {
  // variable declarations
  untilAjax([{
    url: 'url2',
    dataType: 'json',
    success: function(data) {
      //do something with success data
    }
  }, {
    url: 'url1',
    dataType: 'json',
    success: function(data) {
      //do something with success data
    }
  }, {
    url: 'url2',
    dataType: 'json',
    success: function(response) {
      //do something with success data
    }
  }], function() {
    // logic after all the calls are completed.
  });
}
Sanjeev Kumar Dangi
fuente
2

Le recomiendo usar $ .when () si está comenzando desde cero.

Aunque esta pregunta tiene más de un millón de respuestas, todavía no encontré nada útil para mi caso. Supongamos que tiene que lidiar con una base de código existente, que ya realiza algunas llamadas ajax y no quiere introducir la complejidad de las promesas y / o rehacer todo.

Podemos tomar ventaja de jQuery .data, .ony .triggerlas funciones que han sido una parte de jQuery desde siempre.

Codepen

Lo bueno de mi solución es:

  • es obvio de qué depende exactamente la devolución de llamada

  • a la función triggerNowOrOnLoadedno le importa si los datos ya se han cargado o si todavía estamos esperando por ellos

  • es muy fácil conectarlo a un código existente

$(function() {

  // wait for posts to be loaded
  triggerNowOrOnLoaded("posts", function() {
    var $body = $("body");
    var posts = $body.data("posts");

    $body.append("<div>Posts: " + posts.length + "</div>");
  });


  // some ajax requests
  $.getJSON("https://jsonplaceholder.typicode.com/posts", function(data) {
    $("body").data("posts", data).trigger("posts");
  });

  // doesn't matter if the `triggerNowOrOnLoaded` is called after or before the actual requests 
  $.getJSON("https://jsonplaceholder.typicode.com/users", function(data) {
    $("body").data("users", data).trigger("users");
  });


  // wait for both types
  triggerNowOrOnLoaded(["posts", "users"], function() {
    var $body = $("body");
    var posts = $body.data("posts");
    var users = $body.data("users");

    $body.append("<div>Posts: " + posts.length + " and Users: " + users.length + "</div>");
  });

  // works even if everything has already loaded!
  setTimeout(function() {

    // triggers immediately since users have been already loaded
    triggerNowOrOnLoaded("users", function() {
      var $body = $("body");
      var users = $body.data("users");

      $body.append("<div>Delayed Users: " + users.length + "</div>");
    });

  }, 2000); // 2 seconds

});

// helper function
function triggerNowOrOnLoaded(types, callback) {
  types = $.isArray(types) ? types : [types];

  var $body = $("body");

  var waitForTypes = [];
  $.each(types, function(i, type) {

    if (typeof $body.data(type) === 'undefined') {
      waitForTypes.push(type);
    }
  });

  var isDataReady = waitForTypes.length === 0;
  if (isDataReady) {
    callback();
    return;
  }

  // wait for the last type and run this function again for the rest of the types
  var waitFor = waitForTypes.pop();
  $body.on(waitFor, function() {
    // remove event handler - we only want the stuff triggered once
    $body.off(waitFor);

    triggerNowOrOnLoaded(waitForTypes, callback);
  });
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<body>Hi!</body>

cilf
fuente
2

Estoy usando la verificación de tamaño cuando se completa toda la carga ajax

function get_ajax(link, data, callback) {
    $.ajax({
        url: link,
        type: "GET",
        data: data,
        dataType: "json",
        success: function (data, status, jqXHR) {
            callback(jqXHR.status, data)
        },
        error: function (jqXHR, status, err) {
            callback(jqXHR.status, jqXHR);
        },
        complete: function (jqXHR, status) {
        }
    })
}

function run_list_ajax(callback){
    var size=0;
    var max= 10;
    for (let index = 0; index < max; index++) {
        var link = 'http://api.jquery.com/ajaxStop/';
        var data={i:index}
        get_ajax(link,data,function(status, data){
            console.log(index)
            if(size>max-2){
                callback('done')
            }
            size++
            
        })
    }
}

run_list_ajax(function(info){
    console.log(info)
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>

tranchau
fuente
aprobado a su ejemplo.
MarwaAhmad
2

Para ampliar la respuesta de Alex, tengo un ejemplo con argumentos y promesas variables. Quería cargar imágenes a través de ajax y mostrarlas en la página después de que se hayan cargado todas.

Para hacer eso, utilicé lo siguiente:

let urlCreator = window.URL || window.webkitURL;

// Helper function for making ajax requests
let fetch = function(url) {
    return $.ajax({
        type: "get",
        xhrFields: {
            responseType: "blob"
        },
        url: url,
    });
};

// Map the array of urls to an array of ajax requests
let urls = ["https://placekitten.com/200/250", "https://placekitten.com/300/250"];
let files = urls.map(url => fetch(url));

// Use the spread operator to wait for all requests
$.when(...files).then(function() {
    // If we have multiple urls, then loop through
    if(urls.length > 1) {
        // Create image urls and tags for each result
        Array.from(arguments).forEach(data => {
            let imageUrl = urlCreator.createObjectURL(data[0]);
            let img = `<img src=${imageUrl}>`;
            $("#image_container").append(img);
        });
    }
    else {
        // Create image source and tag for result
        let imageUrl = urlCreator.createObjectURL(arguments[0]);
        let img = `<img src=${imageUrl}>`;
        $("#image_container").append(img);
    }
});

Actualizado para funcionar para urls individuales o múltiples: https://jsfiddle.net/euypj5w9/

GammaGames
fuente
2

Como se mencionó en otras respuestas, puede usar ajaxStop()para esperar hasta que se completen todas las solicitudes de ajax.

$(document).ajaxStop(function() {
     // This function will be triggered every time any ajax request is requested and completed
});

Si desea hacerlo para una ajax()solicitud específica, lo mejor que puede hacer es utilizar el complete()método dentro de la solicitud ajax determinada:

$.ajax({
    type: "POST",
    url: "someUrl",
    success: function(data) {
        // This function will be triggered when ajax returns a 200 status code (success)
    },
    complete: function() {
        // This function will be triggered always, when ajax request is completed, even it fails/returns other status code
    },
    error: function() {
        // This will be triggered when ajax request fail.
    }
});


Pero, ¿ si necesita esperar solo unas pocas y ciertas solicitudes de ajax? Use las maravillosas promesas de JavaScript para esperar hasta que estos ajax que desea esperar estén listos. Hice un ejemplo breve, fácil y legible para mostrarle cómo funciona promesas con ajax.
Por favor, eche un vistazo al siguiente ejemplo . Solía setTimeoutaclarar el ejemplo.

// Note:
// resolve() is used to mark the promise as resolved
// reject() is used to mark the promise as rejected

$(document).ready(function() {
    $("button").on("click", function() {

        var ajax1 = new Promise((resolve, reject) => {
            $.ajax({
                type: "GET",
                url: "https://miro.medium.com/max/1200/0*UEtwA2ask7vQYW06.png",
                xhrFields: { responseType: 'blob'},
                success: function(data) {
                    setTimeout(function() {
                        $('#image1').attr("src", window.URL.createObjectURL(data));
                        resolve(" Promise ajax1 resolved");
                    }, 1000);
                },
                error: function() {
                    reject(" Promise ajax1 rejected");
                },
            });
        });

        var ajax2 = new Promise((resolve, reject) => {
            $.ajax({
                type: "GET",
                url: "https://cdn1.iconfinder.com/data/icons/social-media-vol-1-1/24/_github-512.png",
                xhrFields: { responseType: 'blob' },
                success: function(data) {
                    setTimeout(function() {
                         $('#image2').attr("src", window.URL.createObjectURL(data));
                         resolve(" Promise ajax2 resolved");
                    }, 1500);
                },
                error: function() {
                    reject(" Promise ajax2 rejected");
                },
            });
        });

        var ajax3 = new Promise((resolve, reject) => {
            $.ajax({
                type: "GET",
                url: "https://miro.medium.com/max/632/1*LUfpOf7teWvPdIPTBmYciA.png",
                xhrFields: { responseType: 'blob' },
                success: function(data) {
                    setTimeout(function() {
                         $('#image3').attr("src", window.URL.createObjectURL(data));
                         resolve(" Promise ajax3 resolved");
                    }, 2000);
                },
                error: function() {
                    reject(" Promise ajax3 rejected");
                },
            });
        });
        
        Promise.all([ajax1, ajax2, ajax3]).then(values => {
            console.log("We waited until ajax ended: " + values);
            console.log("My few ajax ended, lets do some things!!")
        }, reason => {
            console.log("Promises failed: " + reason);
        });
        
        // Or if you want wait for them individually do it like this
        // ajax1.then(values => {
        //    console.log("Promise 1 resolved: " + values)
        // }, reason => {
        //     console.log("Promise 1 failed: " + reason)
        // });
    });

});
img {
  max-width: 200px;
  max-height: 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button>Make AJAX request</button>
<div id="newContent">
    <img id="image1" src="">
    <img id="image2" src="">
    <img id="image3" src="">
</div>

Surfista de plata
fuente
0

Encontré manera simple, usando shift()

function waitReq(id)
{
  jQuery.ajax(
  {
    type: 'POST',
    url: ajaxurl,
    data:
    {
      "page": id
    },
    success: function(resp)
    {
      ...........
      // check array length if not "0" continue to use next array value
      if(ids.length)
      {
        waitReq(ids.shift()); // 2
      )
    },
    error: function(resp)
    {
      ....................
      if(ids.length)
      {
        waitReq(ids.shift());
      )
    }
  });
}

var ids = [1, 2, 3, 4, 5];    
// shift() = delete first array value (then print)
waitReq(ids.shift()); // print 1
Uingtea
fuente
0

Mi solución es la siguiente

var request;
...
'services': {
  'GetAddressBookData': function() {
    //This is the primary service that loads all addressbook records 
    request = $.ajax({
      type: "POST",
      url: "Default.aspx/GetAddressBook",
      contentType: "application/json;",
      dataType: "json"
    });
  },

  ...

  'apps': {
    'AddressBook': {
      'data': "",
      'Start': function() {
          ...services.GetAddressBookData();
          request.done(function(response) {
            trace("ajax successful");
            ..apps.AddressBook.data = response['d'];
            ...apps.AddressBook.Filter();
          });
          request.fail(function(xhr, textStatus, errorThrown) {
            trace("ajax failed - " + errorThrown);
          });

Funcionó bastante bien. He intentado muchas formas diferentes de hacerlo, pero descubrí que es la más simple y reutilizable. Espero eso ayude

Eric Sean Moore
fuente
0

Mira mi solución:

1.Inserte esta función (y variable) en su archivo javascript:

var runFunctionQueue_callback;

function runFunctionQueue(f, index, callback) {

  var next_index = index + 1

  if (callback !== undefined) runFunctionQueue_callback = callback;

  if (f[next_index] !== undefined) {
    console.log(index + ' Next function avalaible -> ' + next_index);
    $.ajax({
      type: 'GET',
      url: f[index].file,
      data: (f[index].data),
      complete: function() {
        runFunctionQueue(f, next_index);
      }
    });
  } else {
    console.log(index + ' Last function');
    $.ajax({
      type: 'GET',
      url: f[index].file,
      data: (f[index].data),
      async: false,
      complete: runFunctionQueue_callback
    });
  }
}

2. Construya una matriz con sus solicitudes, como esta:

var f = [
           {file: 'file_path', data: {action: 'action', data: 'any_data}},
           {file: 'file_path', data: {action: 'action', data: 'any_data}},
           {file: 'file_path', data: {action: 'action', data: 'any_data}},
           {file: 'file_path', data: {action: 'action', data: 'any_data}}
        ];

3.Cree la función de devolución de llamada:

function Function_callback() {
  alert('done');
}

4. Llame a la función runFunctionQueue con parámetros:

runFunctionQueue(f, 0, QuestionInsert_callback);
// first parameter: array with requests data
// second parameter: start from first request
// third parameter: the callback function
Briganti
fuente
-4

Intenta de esta manera. haga un bucle dentro de la función de script java para esperar hasta que finalice la llamada ajax.

function getLabelById(id)
{
    var label = '';
    var done = false;
    $.ajax({
       cache: false,
       url: "YourMvcActionUrl",
       type: "GET",
       dataType: "json",
       async: false,
       error: function (result) {
         label='undefined';
         done = true;
        },
       success: function (result) {
            label = result.Message;
            done = true;
        }
     });

   //A loop to check done if ajax call is done.
   while (!done)
   {
      setTimeout(function(){ },500); // take a sleep.
   }

    return label;
}
ChinaHelloWorld
fuente
1
Tu setTimeout()NO take a sleep. En este caso, simplemente bloquea todas las pestañas hasta que se donehaga realidad.
Alexis Wilke
1
Creo que este es el tema que pide: "Espere hasta que todas las solicitudes de jQuery Ajax estén hechas".
ChinaHelloWorld
1
¿Has probado este código? mi expectativa es que doneeso nunca será cierto mientras el ciclo while todavía se esté ejecutando. Si el ciclo while se está ejecutando, el ciclo de eventos no puede continuar y, por lo tanto, nunca ejecutará la devolución de llamada para el éxito de ajax.
Kevin B