Attendere il completamento di tutte le richieste jQuery Ajax?


675

Come faccio ad aspettare una funzione fino a quando tutte le richieste jQuery Ajax non vengono eseguite all'interno di un'altra funzione?

In breve, devo aspettare che vengano fatte tutte le richieste Ajax prima di eseguire il successivo. Ma come?


Come stai chiamando le tue richieste Ajax originali?
NakedBrunch,

2
Cosa intendi con "fatto"? Lo capisco come "tutte le richieste sono state completate correttamente o meno" (risolte o rifiutate). Ma potresti voler dire "tutte le richieste sono state completate correttamente" (risolto). vedi tutte le varianti in api.jquery.com/category/deferred-object
Adrien Be

Risposte:


911

jQuery ora definisce una funzione quando per questo scopo.

Accetta qualsiasi numero di oggetti rinviati come argomenti ed esegue una funzione quando tutti risolvono.

Ciò significa che se si desidera avviare (ad esempio) quattro richieste Ajax, quindi eseguire un'azione al termine, è possibile fare qualcosa del genere:

$.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,            
        ...
    });
}

A mio avviso, crea una sintassi chiara e chiara ed evita il coinvolgimento di variabili globali come ajaxStart e ajaxStop, che potrebbero avere effetti collaterali indesiderati durante lo sviluppo della pagina.

Se non sai in anticipo quanti argomenti ajax devi aspettare (cioè vuoi usare un numero variabile di argomenti), può ancora essere fatto ma è solo un po 'più complicato. Vedi Passa in una matrice di Deferreds a $ .when () (e forse jQuery .quando si risolve con un numero variabile di argomenti ).

Se hai bisogno di un controllo più approfondito sulle modalità di errore degli script ajax ecc., Puoi salvare l'oggetto restituito da .when(): è un oggetto jQuery Promise che comprende tutte le query ajax originali. È possibile chiamare .then()o .fail()su di esso per aggiungere gestori di successo / fallimento dettagliati.


46
Questo dovrebbe essere contrassegnato come una risposta corretta perché è semplice, efficiente e funziona alla grande. Inoltre, va notato che $.whenrestituisce un Promiseoggetto che ha metodi più utili, non solo .done. Ad esempio, con il .then(onSuccess, onFailure)metodo è possibile reagire quando entrambe le richieste hanno esito positivo o almeno una di esse non riesce.
Skalee,

2
È possibile raggruppare le richieste ajax1..4 in un array e passarlo?
Andig

33
Fai attenzione al failcaso. Diversamente done, failil primo colpo fallisce immediatamente e ignora i rimanenti rinvii.
Ryan Mohr,

1
@skalee grazie per aver evidenziato il fatto che una onFailurefunzione potrebbe essere collegata. Come ho sottolineato in un commento alla domanda del PO: potrebbe voler indicare più precisamente cosa intendesse per "fatto". "Ryan Mohr" ha anche avuto un ottimo punto in merito al fatto che failsi comporta in modo diverso poiché done, alcune ulteriori letture da fare su Promisessuppongo html5rocks.com/en/tutorials/es6/promises
Adrien Be

1
È bello offrire alle persone un'esposizione al metodo when e alle promesse in generale, ma penso che questa non sia la risposta migliore. Se una di queste funzioni ajax in qualsiasi punto della linea crea un'altra richiesta ajax, e quindi non integra correttamente quella nuova promessa nella catena ... quelle richieste sfuggiranno a questa tecnica. Ad esempio, non posso usare questa tecnica senza modificare la libreria di Shopify che sto usando per il comportamento di aggiunta al carrello di Ajax, perché non è stata scritta in modo "promettente" e non restituisce mai gli oggetti xhr che crea. ha senso? Comunque un'ottima risposta, comunque!
Ziggy,

292

Se vuoi sapere quando tutte le ajax richieste sono finite nel tuo documento, indipendentemente da quante ne esistano, usa semplicemente l' evento $ .ajaxStop in questo modo:

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

In questo caso, non è necessario indovinare quante richieste stanno accadendo nell'applicazione, che potrebbero finire in futuro, né scavare in funzioni logiche complesse o trovare quali funzioni stanno facendo HTTP(S)richieste.

$.ajaxStopqui può anche essere associato a qualsiasi HTMLnodo che ritieni possa essere modificato da requst.


Aggiornamento:
se si desidera attenersi alla ESsintassi, è possibile utilizzare Promise.all per ajaxmetodi noti :

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

Un punto interessante è che funziona sia con Promisese $.ajaxrichieste.

Ecco la dimostrazione di jsFiddle .


Aggiornamento 2:
versione ancora più recente che utilizza la sintassi async / await :

try {
  const results = await Promise.all([ajax1(), ajax2()])
  // do other actions
} catch(ex) { }

16
+1 Molto meglio delle altre risposte nel caso in cui tu abbia a che fare con script di terze parti con callback / chiusure anonime.
Kaiser

5
@kaiser Punto valido ma non è quello che la domanda stava ponendo. Non è molto utile se non si desidera attendere il ritorno di tutte le chiamate AJAX. La domanda è specifica sull'attesa delle chiamate AJAX effettuate da soli (chiamate all'interno di un'altra funzione, come ha scritto l'OP). Alcuni altri codici potrebbero aver effettuato un'altra chiamata AJAX che non si desidera attendere.
Juan Mendes,

6
Rispetto alla soluzione when (), ha il vantaggio di funzionare anche se il numero di chiamate ajax non è noto.
Alexis Dufrenoy,

5
Rispetto alla soluzione when (), ha il grande svantaggio di non funzionare bene insieme ad altri componenti, poiché condivide uno stato globale a livello di documento. Se c'è un lungo polling in corso continuamente, potrebbe anche non sparare mai.
Bergi,

3
Non hai ragione @AdrienBe, ajaxStop gestisce tutte le richieste ajax, indipendentemente dal fatto che abbiano successo o meno, proprio come prova delle mie parole guardate questo jsfiddle.net/36votxba/2
Arsen Khachaturyan

32

Ho trovato una buona risposta da parte gnarf la mia auto, che è esattamente quello che stavo cercando :)

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);

Quindi puoi aggiungere una richiesta Ajax alla coda in questo modo:

$.ajaxQueue({
        url: 'page.php',
        data: {id: 1},
        type: 'POST',
        success: function(data) {
            $('#status').html(data);
        }
    });

37
Sembra che tu abbia dimenticato di dare la giusta attribuzione a questa risposta , l'ho aggiunta.
Tim Post

21

Usa l' ajaxStopevento.

Ad esempio, supponiamo che tu abbia un messaggio di caricamento ... durante il recupero di 100 richieste Ajax e desideri nascondere quel messaggio una volta caricato.

Dal documento jQuery :

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

Nota che attenderà che tutte le richieste Ajax vengano fatte su quella pagina.


5
Questo presuppone che tu sappia che non ci saranno altre richieste AJAX sulla pagina, non un ottimo presupposto
Juan Mendes,

A partire da jQuery 1.8, il metodo .ajaxStop () deve essere allegato solo al documento.
Geomorillo,

1
Correggimi se sbaglio, ma questo non trasformerà il tuo progetto in un sito "moduli web vecchia scuola"? Voglio dire se tutta la tua pagina deve attendere una richiesta prima che possa continuare, qual è il punto della richiesta Ajax in primo luogo?
BillRuhl,

@BillRuhl nel nostro caso, sto facendo un giro in una raccolta jquery per creare nuove cose e ho bisogno di conoscere l'intera raccolta quando è fatta, prima di apportare alcune modifiche al layout. Non sembra un caso particolarmente insolito. Sarebbe male se un gruppo di altre cose Ajax potrebbe essere in corso, ma non lo sarà, qui.
eone

21

NOTA: le risposte di cui sopra utilizzano funzionalità che non esistevano al momento in cui questa risposta è stata scritta. Raccomando di usarejQuery.when() invece di questi approcci, ma lascio la risposta per scopi storici.

-

Probabilmente potresti cavartela con un semplice semaforo di conteggio, sebbene il modo in cui lo implementerai dipenderà dal tuo codice. Un semplice esempio potrebbe essere qualcosa come ...

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;

Se volevi che funzionasse come {async: false} ma non volevi bloccare il browser, potresti ottenere lo stesso risultato con una coda 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();
    });
});

10
Questo sembra complicare eccessivamente un banale problema.
Chris,

2
Non è poi così complicato. Il conteggio dei semafori è un meccanismo comune in CS. Se preferite, tuttavia, l'esempio usando le code jQuery funzionerebbe anche senza dover implementare il semaforo da soli.
BBonifield,

1
Non vedo un problema con il contatore dei semafori, tuttavia, vedo un problema con l'idea di avere QUATTRO funzioni per gestire il callback risultante. È necessario prima definire una funzione, quindi fare riferimento a tale funzione in ciascuna .get(). In questo modo almeno non duplicare quel codice. Non solo, ma dichiarando function(){}ogni volta alloca memoria ogni volta! Piuttosto cattiva pratica se si potesse chiamare una funzione definita staticamente.
Alexis Wilke,

1
@AlexisWilke Questa è una risposta di 4,5 anni, che doveva essere un esempio di come funzionano i semafori e le code. Stai pensando un po 'troppo a questo proposito, e non penso che la CAPITALIZZAZIONE PER FARE UN PUNTO sia necessaria.
BBonifield,

2
Beh ... non sono io quello che ti ha dato un -1 ... e capisco che le risposte tendono ad invecchiare. Tuttavia, le persone continuano a trovarle e, per quanto ne so, non è vietato fornire informazioni a persone che potrebbero usarle ancora oggi.
Alexis Wilke,

8

javascript è basato su eventi, quindi non dovresti mai aspettare , piuttosto imposta hook / callback

Probabilmente puoi semplicemente usare i metodi success / complete di jquery.ajax

Oppure potresti usare .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...
  }
});

anche se dovresti pubblicare uno pseudocodice di come le tue richieste ajax vengono chiamate per essere più precise ...


8

Una piccola soluzione è qualcosa del genere:

// 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 speranza può essere utile ...


Mentre le altre risposte sono tecnicamente migliori poiché è molto più facile da capire, questa mi piace molto. Bello!
Jay,

4

jQuery consente di specificare se si desidera che la richiesta ajax sia asincrona o meno. Puoi semplicemente rendere sincrone le richieste ajax e il resto del codice non verrà eseguito fino alla loro restituzione.

Per esempio:

jQuery.ajax({ 
    async: false,
    //code
});

42
Una cosa da notare è che l'uso di {async: false} può bloccare temporaneamente il browser. api.jquery.com/jQuery.ajax
BBonifield

30
Ciò è contrario alla pratica standard jQuery / Javascript. AJAX dovrebbe sempre essere asincrono. Dovresti invece usare jQuery.when ().
SystemParadox,

43
È una pessima idea! Non farlo mai ! Blocco = non risponde affatto alle azioni dell'utente, nemmeno allo scorrimento o altro! (Inoltre, async: false sarà deprecato in jQuery 1.8.)
skalee

5
Soprattutto se la richiesta fallisce o impiega molto tempo per qualche motivo imprevedibile (che, secondo la Legge di Murphy, è destinata ad accadere!), Questa è generalmente una cattiva idea per il codice di produzione a causa del blocco del browser come indicato sopra.
Alex,

27
Questa è un'idea orribilmente negativa. NON UTILIZZARE QUESTA RISPOSTA.
Tauren,

2

Se hai bisogno di qualcosa di semplice; una volta e richiamata

        //multiple ajax calls above
        var callback = function () {
            if ($.active !== 0) {
                setTimeout(callback, '500');
                return;
            }
            //whatever you need to do here
            //...
        };
        callback();

4
può generare un ciclo infinito!
Diego Favero,

2
Questo è un ciclo infinito? Quando? Quando l'AJAX non ritorna mai?
Jonathan,

2

Inoltre puoi usare async.js .

Penso che sia meglio di $ .quando perché è possibile unire tutti i tipi di chiamate asincrone che non supportano le promesse out-of-the-box come timeout, chiamate SqlLite ecc. E non solo richieste Ajax.


2

Sulla base della risposta di @BBonifield, ho scritto una funzione di utilità in modo che la logica dei semafori non si diffonda in tutte le chiamate ajax.

untilAjax è la funzione di utilità che richiama una funzione di richiamata quando tutte le chiamate ajax sono state completate.

ajaxObjsè una matrice di oggetti di impostazione Ajax [http://api.jquery.com/jQuery.ajax/].

fn è la funzione di richiamata

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;
  };

Esempio: la doSomethingfunzione usa 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.
  });
}

2

Consiglio vivamente di usare $ .when () se inizi da zero.

Anche se questa domanda ha oltre un milione di risposte, non ho ancora trovato nulla di utile per il mio caso. Supponiamo che tu abbia a che fare con una base di codice esistente, già facendo alcune chiamate Ajax e non vuoi introdurre la complessità delle promesse e / o rifare il tutto.

Possiamo facilmente usufruire di jQuery .data, .one .triggerfunzioni che hanno fatto parte di jQuery da sempre.

Codepen

La cosa buona della mia soluzione è:

  • è ovvio da cosa dipende esattamente il callback

  • alla funzione triggerNowOrOnLoadednon importa se i dati sono già stati caricati o se li stiamo ancora aspettando

  • è semplicissimo collegarlo a un codice esistente

$(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>


2

Sto usando il controllo dimensioni quando tutto il caricamento Ajax è stato completato

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>


pollice in alto al tuo esempio.
MarwaAhmad,

2

Per espandere la risposta di Alex, ho un esempio con argomenti e promesse variabili. Volevo caricare le immagini tramite Ajax e visualizzarle sulla pagina dopo averle tutte caricate.

Per fare ciò, ho usato quanto segue:

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);
    }
});

Aggiornato per funzionare con URL singoli o multipli: https://jsfiddle.net/euypj5w9/


2

Come altre risposte menzionate, puoi usare ajaxStop()per attendere fino al completamento di tutte le richieste Ajax.

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

Se vuoi farlo per una ajax()richiesta specifica, la cosa migliore che puoi fare è usare il complete()metodo all'interno di una determinata richiesta Ajax:

$.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.
    }
});


Ma, se hai bisogno di aspettare solo poche e certe richieste ajax da fare? Usa le meravigliose promesse javascript per aspettare fino a quando questi ajax che vuoi aspettare sono terminati. Ho fatto un esempio breve, facile e leggibile per mostrarti come funzionano le promesse con Ajax.
Dai un'occhiata al prossimo esempio . Ho usato setTimeoutper chiarire l'esempio.

// 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>


0

Ho trovato un modo semplice, 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

0

La mia soluzione è la seguente

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);
          });

Ha funzionato abbastanza bene. Ho provato molti modi diversi per farlo, ma ho scoperto che questo è il più semplice e riutilizzabile. Spero che sia d'aiuto


0

Guarda la mia soluzione:

1.Inserire questa funzione (e variabile) nel file 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. Buil un array con le tue richieste, in questo modo:

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.Creazione della funzione di richiamata:

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

4.Chiama la funzione runFunctionQueue con parametri:

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


-4

Prova in questo modo. crea un ciclo all'interno della funzione java script per attendere fino al termine della chiamata 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;
}

1
Il tuo setTimeout()NON take a sleep. In questo caso, basta bloccare tutte le schede fino a quando non donediventa vero.
Alexis Wilke,

1
Penso che questo argomento richieda: "Aspetta che tutte le richieste jQuery Ajax siano completate".
ChinaHelloWorld

1
Hai provato questo codice? la mia aspettativa è che donenon sarà mai vero mentre il ciclo while è ancora in esecuzione. Se il ciclo while è in esecuzione, il ciclo degli eventi non può continuare e pertanto non eseguirà mai la richiamata per il successo ajax.
Kevin B,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.