web-dev-qa-db-fra.com

Comment tout faire AJAX appels séquentiels?

J'utilise jQuery. Et je ne veux pas d'appels parallèles AJAX sur mon application, chaque appel doit attendre le précédent avant de commencer. Comment l'implémenter? Il n'y a aucune aide?

UPDATES'il existe une version synchrone de XMLHttpRequest ou de jQuery.post, j'aimerais le savoir. Mais séquentiel! = Synchrone, et je voudrais une solution asynchrone et séquentielle.

23
Jader Dias

Il existe un bien meilleur moyen de le faire que d’utiliser des appels ajax synchrones. Jquery ajax renvoie un différé afin que vous puissiez simplement utiliser un chaînage de canaux pour vous assurer que chaque appel ajax se termine avant les prochaines exécutions. Voici un exemple de travail avec un exemple plus détaillé que vous pouvez jouer avec sur jsfiddle .

// How to force async functions to execute sequentially 
// by using deferred pipe chaining.

// The master deferred.
var dfd = $.Deferred(),  // Master deferred
    dfdNext = dfd; // Next deferred in the chain
    x = 0, // Loop index
    values = [], 

    // Simulates $.ajax, but with predictable behaviour.
    // You only need to understand that higher 'value' param 
    // will finish earlier.
    simulateAjax = function (value) {
        var dfdAjax = $.Deferred();

        setTimeout(
            function () {
                dfdAjax.resolve(value);
            },
            1000 - (value * 100)
        );

        return dfdAjax.promise();
    },

    // This would be a user function that makes an ajax request.
    // In normal code you'd be using $.ajax instead of simulateAjax.
    requestAjax = function (value) {
        return simulateAjax(value);
    };

// Start the pipe chain.  You should be able to do 
// this anywhere in the program, even
// at the end,and it should still give the same results.
dfd.resolve();

// Deferred pipe chaining.
// What you want to note here is that an new 
// ajax call will not start until the previous
// ajax call is completely finished.
for (x = 1; x <= 4; x++) {

    values.Push(x);

    dfdNext = dfdNext.pipe(function () {
        var value = values.shift();
        return requestAjax(value).
            done(function(response) {
                // Process the response here.

            });

    });

}

Certaines personnes ont fait remarquer qu'elles n'avaient aucune idée de ce que faisait le code. Pour le comprendre, vous devez d’abord comprendre les promesses javascript. Je suis presque sûr que les promesses deviendront bientôt une fonctionnalité native du langage javascript, ce qui devrait vous inciter à apprendre.

16
Todd Chaffee

Vous avez deux choix auxquels je peux penser. La première consiste à les enchaîner par des rappels. L'autre consiste à rendre les appels synchrones plutôt qu'async.

Y a-t-il une raison pour laquelle vous les voulez séquentielles? Cela ralentira les choses.

Pour rendre l'appel synchrone, définissez l'option async dans l'appel Ajax sur false. Voir la documentation à http://docs.jquery.com/Ajax/jQuery.ajax#options (cliquez sur l'onglet Options pour les voir).

6
Nosredna

Définissez l'option async sur false, par exemple,

$.ajax({ async: false /*, your_other_ajax_options_here */ });

Référence: Ajax/jQuery.ajax

3
Joe Chung

Vous pouvez essayer le javascript narratif http://www.neilmix.com/narrativejs/doc/

Je ne l'ai jamais utilisé moi-même cependant. Si je voulais faire cela, je mettrais en place une sorte d’abstraction pour enchaîner les actions asynchrones. Comme d'autres l'ont dit, la version synchrone de l'objet ajax bloque le traitement des événements pendant l'attente d'une réponse. Cela a pour effet de donner l'impression que le navigateur est gelé jusqu'à ce qu'il reçoive une réponse.

2
Breton

Regardez ceci: http://docs.jquery.com/Ajax/jQuery.ajax (cliquez sur l'onglet "options").

Cependant, rappelez-vous qu'un appel synchrone gèlera la page jusqu'à la réception de la réponse. Par conséquent, il ne pourra pas être utilisé sur un site de production, car les utilisateurs s'énervent s'ils doivent attendre 30 secondes avec leur navigateur bloqué.

EDIT: ok, avec votre mise à jour, il est plus clair ce que vous voulez réaliser;)

Donc, votre code peut ressembler à ceci:

    $.getJSON("http://example.com/jsoncall", function(data) {
        process(data);
        $.getJSON("http://example.com/jsoncall2", function (data) {
            processAgain(data);
            $.getJSON("http://example.com/anotherjsoncall", function(data) {
                processAgainAndAgain(data);
            });
        });
    });

De cette façon, le deuxième appel ne sera émis que lorsque la réponse au premier appel aura été reçue et traitée, et le troisième appel ne sera émis que lorsque la réponse au deuxième appel aura été reçue et traitée. Ce code est pour getJSON mais il peut être adapté à $ .ajax.

1
FWH

La meilleure façon de le faire est d’enchaîner les rappels, comme l’a dit Nosredna. Je ne recommanderais pas d'utiliser XMLHttpRequest synchrone car ils verrouillent toute votre application.

Autant que je sache, il n'y a pas beaucoup d'aide pour cela, mais vous pouvez faire quelque chose qui ressemble à une FIFO de rappel.

1
Gab Royer
1
llamerr
(async () => { 
  for(f of ['1.json','2.json','3.json']){
    var json = await $.getJSON(f);
    console.log(json)
 };
})()
  1. demande 3 fichiers json avec des appels jQuery ajax
  2. processus en séquence (pas en parallèle) avec wait
  3. fonctionne dans Chrome/Firefox/Edge (à partir du 30/01/2018)

plus à MDN

0
Rm558

Les appels synchrones ne sont pas nécessairement plus lents, si vous avez une application où AJAX appelle open, poste sur, puis ferme une socket, plusieurs appels à la socket n'ont pas de sens car certains connexion, auquel cas, mettre les données en file d'attente de sorte qu'elles ne soient envoyées que lorsque l'appel précédent AJAX est terminé, signifie un débit de données beaucoup plus élevé.

0
tomski777