Attendez que toutes les requêtes jQuery Ajax soient terminées?

675

Comment faire attendre une fonction jusqu'à ce que toutes les requêtes jQuery Ajax soient effectuées dans une autre fonction?

En bref, je dois attendre que toutes les requêtes Ajax soient effectuées avant d'exécuter la suivante. Mais comment?

jamietelin
la source
Comment appelez-vous vos demandes ajax d'origine?
NakedBrunch du
2
Qu'entendez-vous par «fait»? Je le comprends comme "toutes les demandes se sont terminées avec succès ou non" (résolues ou rejetées). Mais vous pouvez vouloir dire «toutes les demandes se sont terminées avec succès» (résolues). voir toutes les variations dans api.jquery.com/category/deferred-object
Adrien Be

Réponses:

911

jQuery définit désormais une fonction when à cet effet.

Il accepte un nombre illimité d'objets différés comme arguments et exécute une fonction lorsque tous se résolvent.

Cela signifie que si vous souhaitez lancer (par exemple) quatre requêtes ajax, puis effectuer une action une fois qu'elles sont terminées, vous pouvez faire quelque chose comme ceci:

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

À mon avis, cela permet une syntaxe claire et claire, et évite d'impliquer des variables globales telles que ajaxStart et ajaxStop, qui pourraient avoir des effets secondaires indésirables lors du développement de votre page.

Si vous ne savez pas à l'avance combien d'arguments ajax vous devez attendre (c'est-à-dire que vous voulez utiliser un nombre variable d'arguments), cela peut toujours être fait mais c'est juste un peu plus compliqué. Voir Passer dans un tableau de différés à $ .when () (et peut-être jQuery .when lors du dépannage avec un nombre variable d'arguments ).

Si vous avez besoin d'un contrôle plus approfondi sur les modes de défaillance des scripts ajax, etc., vous pouvez enregistrer l'objet renvoyé par .when()- c'est un objet jQuery Promise englobant toutes les requêtes ajax d'origine. Vous pouvez appeler .then()ou .fail()dessus pour ajouter des gestionnaires de réussite / échec détaillés.

Alex
la source
46
Cela devrait être marqué comme une réponse correcte car c'est simple, efficace et fonctionne très bien. En outre, il convient de noter que $.whenrenvoie un Promiseobjet qui a des méthodes plus utiles, non seulement .done. Par exemple, avec la .then(onSuccess, onFailure)méthode, vous pouvez réagir lorsque les deux demandes aboutissent ou au moins l'une d'entre elles échoue.
skalee
2
Est-il possible de regrouper les requêtes ajax1..4 dans un tableau et de passer cela?
andig
33
Soyez prudent avec le failcas. Contrairement à done, failtire immédiatement sur le premier échec et ne tient pas compte des différés restants.
Ryan Mohr
1
@skalee merci d'avoir souligné qu'une onFailurefonction pouvait être attachée. Comme je l'ai souligné dans un commentaire à la question du PO: il voudra peut-être indiquer plus précisément ce qu'il entendait par "fait". "Ryan Mohr" avait également un très bon point concernant le fait qu'il failse comporte différemment car done, quelques lectures supplémentaires à faire sur Promisesje suppose que html5rocks.com/en/tutorials/es6/promises
Adrien Be
1
C'est formidable de donner aux gens une exposition à la méthode Quand et aux promesses en général, mais je pense que ce n'est pas la meilleure réponse. Si l'une de ces fonctions ajax quelque part sur la ligne crée une autre demande ajax, puis n'intègre pas correctement cette nouvelle promesse dans la chaîne ... ces demandes échapperont à cette technique. Par exemple, je ne peux pas utiliser cette technique sans modifier la bibliothèque Shopify que j'utilise pour le comportement d'ajax add-to-cart, car elle n'a pas été écrite de manière `` promise '' et ne renvoie jamais les objets xhr qu'elle crée. Est-ce que ça a du sens? Pourtant, une excellente réponse!
Ziggy
292

Si vous voulez savoir quand toutes les ajax demandes sont terminées dans votre document, quel que soit leur nombre, utilisez simplement l' événement $ .ajaxStop de cette façon:

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

Dans ce cas, vous n'avez pas besoin de deviner combien de demandes se produisent dans l'application, qui pourraient se terminer à l'avenir, ni de creuser dans les fonctions de logique complexe ou de trouver les fonctions qui font des HTTP(S)demandes.

$.ajaxStopici peut également être lié à n'importe quel HTMLnœud qui, selon vous, pourrait être modifié par requst.


Mise à jour:
si vous souhaitez vous en tenir à la ESsyntaxe, vous pouvez utiliser Promise.all pour les ajaxméthodes connues :

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

Un point intéressant ici est qu'il fonctionne à la fois avec Promiseset avec les $.ajaxrequêtes.

Voici la démonstration de jsFiddle .


Mise à jour 2:
version encore plus récente utilisant la syntaxe async / wait :

try {
  const results = await Promise.all([ajax1(), ajax2()])
  // do other actions
} catch(ex) { }
Arsen Khachaturyan
la source
16
+1 Beaucoup mieux que les autres réponses au cas où vous auriez à gérer des scripts tiers avec des rappels / fermetures anonymes.
kaiser
5
@kaiser Point valable mais ce n'est pas ce que la question demandait. Ce n'est pas très bien si vous ne voulez pas attendre le retour de tous les appels AJAX. La question est spécifique sur l'attente des appels AJAX que vous avez effectués vous-même (appelés dans une autre fonction, comme l'OP l'a écrit). Un autre code peut avoir effectué un autre appel AJAX que vous ne voulez pas attendre.
Juan Mendes
6
Par rapport à la solution when (), elle a l'avantage de fonctionner même si le nombre d'appels ajax n'est pas connu.
Alexis Dufrenoy
5
Par rapport à la solution when (), elle présente l'inconvénient majeur de ne pas bien fonctionner avec d'autres composants, car elle partage un état global à l'échelle du document. S'il y a un long scrutin en continu, il pourrait même ne jamais se déclencher.
Bergi
3
Vous n'avez pas raison @AdrienBe, ajaxStop gère toutes les demandes ajax, qu'elles réussissent ou non, tout comme la preuve de mes mots, regardez ce jsfiddle.net/36votxba/2
Arsen Khachaturyan
32

J'ai trouvé une bonne réponse par gnarf mon auto qui est exactement ce que je cherchais :)

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

Ensuite, vous pouvez ajouter une demande ajax à la file d'attente comme ceci:

$.ajaxQueue({
        url: 'page.php',
        data: {id: 1},
        type: 'POST',
        success: function(data) {
            $('#status').html(data);
        }
    });
jamietelin
la source
37
Il semble que vous ayez oublié d'attribuer correctement cette réponse , je l'ai ajouté.
Tim Post
21

Utilisez l' ajaxStopévénement.

Par exemple, supposons que vous ayez un message de chargement ... lors de la récupération de 100 demandes ajax et que vous souhaitiez masquer ce message une fois chargé.

Depuis le doc jQuery :

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

Notez qu'il attendra que toutes les requêtes ajax soient effectuées sur cette page.

olafure
la source
5
Cela suppose que vous savez qu'il n'y aura pas d'autres demandes AJAX sur la page, ce n'est pas une très bonne hypothèse
Juan Mendes
Depuis jQuery 1.8, la méthode .ajaxStop () ne doit être attachée qu'au document.
Geomorillo
1
Corrigez-moi si je me trompe, mais cela ne transformera-t-il pas votre projet en un site de «formulaires Web à l'ancienne»? Je veux dire si vous toute votre page doit attendre une demande avant de pouvoir continuer, alors quel est l'intérêt de la demande ajax en premier lieu?
BillRuhl
@BillRuhl dans notre cas, je passe en revue une collection jquery pour construire de nouvelles choses et j'ai besoin de connaître toute la collection quand c'est fait, avant de faire quelques ajustements de disposition. Cela ne semble pas être un cas particulièrement inhabituel. Ce serait mauvais si un tas d'autres trucs ajax pouvaient être en cours, mais ce ne sera pas le cas ici.
eon
21

REMARQUE: les réponses ci-dessus utilisent des fonctionnalités qui n'existaient pas au moment où cette réponse a été écrite. Je recommande d'utiliser à la jQuery.when()place de ces approches, mais je laisse la réponse à des fins historiques.

-

Vous pourriez probablement vous en tirer avec un simple sémaphore de comptage, bien que la façon dont vous l'implémentiez dépendrait de votre code. Un exemple simple serait quelque chose comme ...

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 vous vouliez que cela fonctionne comme {async: false} mais que vous ne vouliez pas verrouiller le navigateur, vous pourriez accomplir la même chose avec une file d'attente 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
la source
10
Cela semble compliquer excessivement un problème trivial.
Chris
2
Ce n'est vraiment pas si compliqué. Le comptage des sémaphores est un mécanisme courant dans CS. Si vous préférez cependant, l'exemple utilisant les files d'attente jQuery fonctionnerait également sans avoir à implémenter le sémaphore vous-même.
BBonifield
1
Je ne vois pas de problème avec le compteur de sémaphores, cependant, je vois un problème avec l'idée d'avoir QUATRE fonctions pour gérer le rappel résultant. Vous devez d'abord définir une fonction, puis référencer cette fonction dans chacune .get(). De cette façon, au moins, vous ne dupliquez pas ce code. Non seulement cela, mais déclarer un à function(){}chaque fois alloue de la mémoire à chaque fois! Plutôt mauvaise pratique si vous pouviez appeler une fonction définie statiquement.
Alexis Wilke
1
@AlexisWilke Il s'agit d'une réponse vieille de 4,5 ans, et elle devait être un exemple du fonctionnement des sémaphores et des files d'attente. Vous y réfléchissez un peu trop et je ne pense pas que la CAPITALISATION POUR FAIRE UN POINT soit nécessaire.
BBonifield
2
Eh bien ... ce n'est pas moi qui vous ai donné un -1 ... et je comprends que les réponses ont tendance à vieillir. Pourtant, les gens continuent de les trouver et pour autant que je sache, il n'est pas interdit de donner des informations à des personnes qui pourraient potentiellement les utiliser encore aujourd'hui.
Alexis Wilke
8

javascript est basé sur les événements, vous ne devez donc jamais attendre , plutôt définir des hooks / rappels

Vous pouvez probablement simplement utiliser les méthodes succès / complet de jquery.ajax

Ou vous pouvez utiliser .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...
  }
});

bien que vous devriez publier un pseudocode de la façon dont votre (vos) demande (s) ajax est (sont) appelée (s) pour être plus précis ...

Stefano
la source
8

Une petite solution de contournement est quelque chose comme ceci:

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

L'espoir peut être utile ...

Jesfre
la source
Bien que les autres réponses soient techniquement meilleures car elles sont beaucoup plus faciles à comprendre, j'aime beaucoup celle-ci. Agréable!
Jay
4

jQuery vous permet de spécifier si vous souhaitez que la demande ajax soit asynchrone ou non. Vous pouvez simplement rendre les requêtes ajax synchrones, puis le reste du code ne s'exécutera pas avant leur retour.

Par exemple:

jQuery.ajax({ 
    async: false,
    //code
});
shmuel613
la source
42
Une chose à noter est que l'utilisation de {async: false} peut verrouiller temporairement le navigateur. api.jquery.com/jQuery.ajax
BBonifield
30
Cela va à l'encontre de la pratique standard jQuery / Javascript. AJAX est toujours censé être asynchrone. Vous devez utiliser jQuery.when () à la place.
SystemParadox
43
C'est terriblement mauvaise idée! Ne fais jamais ça! Blocage = ne répond pas du tout aux actions de l'utilisateur, même au défilement ou quoi que ce soit! (De plus, async: false va être déconseillé dans jQuery 1.8.)
skalee
5
En particulier, si la demande échoue ou prend du temps pour une raison imprévisible (ce qui, selon la loi de Murphy, est inévitable!), C'est généralement une mauvaise idée pour le code de production en raison du verrouillage du navigateur comme indiqué ci-dessus.
Alex
27
C'est une horriblement mauvaise idée. N'UTILISEZ PAS CETTE RÉPONSE.
Tauren
2

Si vous avez besoin de quelque chose de simple; rappel terminé

        //multiple ajax calls above
        var callback = function () {
            if ($.active !== 0) {
                setTimeout(callback, '500');
                return;
            }
            //whatever you need to do here
            //...
        };
        callback();
Fatmuemoo
la source
4
il peut générer une boucle sans fin!
Diego Favero
2
Ceci est une boucle sans fin? Quand? Quand l'AJAX ne revient jamais?
Jonathan
2

Vous pouvez également utiliser async.js .

Je pense que c'est mieux que $ .when parce que vous pouvez fusionner toutes sortes d'appels asynchrones qui ne prennent pas en charge les promesses prêtes à l'emploi comme les délais d'attente, les appels SqlLite, etc. et pas seulement les demandes ajax.

George Mavritsakis
la source
2

Sur la base de la réponse @BBonifield, j'ai écrit une fonction utilitaire pour que la logique sémaphore ne se répande pas dans tous les appels ajax.

untilAjax est la fonction utilitaire qui appelle une fonction de rappel lorsque tous les ajaxCalls sont terminés.

ajaxObjsest un tableau d'objets de réglage ajax [http://api.jquery.com/jQuery.ajax/].

fn est la fonction de rappel

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

Exemple: doSomethingfonction utilise 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
la source
2

Je recommande fortement d'utiliser $ .when () si vous partez de zéro.

Même si cette question a plus de millions de réponses, je n'ai toujours rien trouvé d'utile pour mon cas. Disons que vous devez gérer une base de code existante, faire déjà des appels ajax et ne pas vouloir introduire la complexité des promesses et / ou refaire le tout.

Nous pouvons facilement profiter de jQuery .data, .onet.trigger les fonctions qui ont été une partie de jQuery depuis toujours.

Codepen

Le bon côté de ma solution est:

  • il est évident de quoi dépend exactement le rappel

  • la fonction triggerNowOrOnLoadedne se soucie pas si les données ont déjà été chargées ou si nous l'attendons toujours

  • il est super facile de le brancher sur un code existant

$(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
la source
2

J'utilise la vérification de la taille lorsque toute la charge ajax est terminée

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
la source
bravo à votre exemple.
MarwaAhmad
2

Pour développer la réponse d'Alex, j'ai un exemple avec des arguments et des promesses variables. Je voulais charger des images via ajax et les afficher sur la page après qu'elles soient toutes chargées.

Pour ce faire, j'ai utilisé ce qui suit:

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

Mis à jour pour fonctionner pour des URL simples ou multiples: https://jsfiddle.net/euypj5w9/

GammaGames
la source
2

Comme d'autres réponses mentionnées, vous pouvez utiliser ajaxStop()pour attendre que toutes les demandes ajax soient terminées.

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

Si vous voulez le faire pour une ajax()demande spécifique, le mieux que vous puissiez faire est d'utiliser la complete()méthode à l'intérieur de la certaine demande 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.
    }
});


Mais, si vous devez attendre seulement quelques demandes ajax et certaines à faire? Utilisez les merveilleuses promesses de javascript pour attendre que ces ajax que vous voulez attendre soient terminés. J'ai fait un exemple bref, facile et lisible pour vous montrer comment fonctionne les promesses avec ajax.
Veuillez jeter un œil à l'exemple suivant . J'avais l'habitude setTimeoutde clarifier l'exemple.

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

Surfeur d'Argent
la source
0

J'ai trouvé un moyen simple, en utilisant 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
la source
0

Ma solution est la suivante

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

A très bien fonctionné. J'ai essayé de nombreuses façons différentes de le faire, mais j'ai trouvé que c'était le plus simple et le plus réutilisable. J'espère que cela aide

Eric Sean Moore
la source
0

Regardez ma solution:

1.Insérez cette fonction (et variable) dans votre fichier 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
    });
  }
}

Construisez un tableau avec vos demandes, comme ceci:

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.Créer une fonction de rappel:

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

4.Appelez la fonction runFunctionQueue avec les paramètres:

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

Essayez de cette façon. faire une boucle à l'intérieur de la fonction de script java pour attendre la fin de l'appel 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
la source
1
Ce setTimeout()n'est PAS le cas take a sleep. Dans ce cas, il vous suffit de bloquer tous les onglets jusqu'à ce qu'il donedevienne vrai.
Alexis Wilke
1
Je pense que c'est ce sujet qui demande: "Attendez que toutes les requêtes jQuery Ajax soient terminées".
ChinaHelloWorld
1
Avez-vous testé ce code? mon attente est que donece ne sera jamais vrai tant que la boucle while est toujours en cours d'exécution. Si la boucle while est en cours d'exécution, la boucle d'événement ne peut pas continuer et ne lancera donc jamais le rappel vers le succès ajax.
Kevin B