Comment faire tous les appels AJAX séquentielle?

j'utilise jQuery. Et je ne veux pas d'appels AJAX parallèles sur mon application, chaque appel doit attendre le précédent avant de commencer. Comment la mettre en œuvre? Il n'y a aucune aide?

UPDATE S'il existe une version synchrone de la XMLHttpRequest ou jQuery.post, je voudrais savoir. Mais séquentielle != synchrone, et je voudrais une solution asynchrone et séquentielle.

23
demandé sur Jader Dias 2009-07-20 07:26:48

11 réponses

Il y a une bien meilleure façon de faire cela que d'utiliser des appels ajax synchrones. Jquery ajax retourne un différé de sorte que vous pouvez juste utiliser canalisation enchaînement pour s'assurer que chaque appel ajax termine avant les prochaines courses. Voici un exemple de travail avec un plus en profondeur exemple, 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 commenté qu'elles n'avaient aucune idée de ce que fait le code. Pour le comprendre, vous devez d'abord comprendre les promesses javascript. Je suis assez sûr promises sera bientôt une fonctionnalité de langage javascript natif, ce qui devrait vous donner une bonne motivation pour apprendre.

16
répondu Todd Chaffee 2014-05-21 17:28:54

Vous avez deux choix que je peux penser. L'une consiste à les enchaîner par des rappels. L'autre consiste à rendre les appels synchrones plutôt qu'asynchrones.

y a-t-il une raison pour laquelle vous les voulez séquentiels? Qui va ralentir les choses.

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

6
répondu Nosredna 2009-07-20 03:37:02

mettre le async option à false, par exemple,

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

Référence: Ajax / jQuery.ajax

3
répondu Joe Chung 2009-07-20 04:17:14

Vous pourriez donner récit javascript essayer http://www.neilmix.com/narrativejs/doc/

je n'ai jamais utilisé moi-même. Si je voulais le faire, je mettrais en place une sorte d'abstraction pour enchaîner les actions asynchrones. Comme d'autres l'ont dit, la version synchone de l'objet ajax bloque le traitement des événements en attendant une réponse. Cela provoque le navigateur ressemble, il est gelé jusqu'à ce qu'il reçoit une réponse.

2
répondu Breton 2009-07-20 03:46:11

la meilleure façon de le faire est d'enchaîner les rappels Comme Nosredna l'a dit. Je ne recommande pas l'utilisation de XMLHttpRequest synchrone car ils verrouillent toute votre application.

il n'y a pas beaucoup d'aide pour ce que je sais, mais vous pourriez faire quelque chose qui ressemble à un FIFO de rappel.

1
répondu Gab Royer 2009-07-20 03:35:55

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

mais rappelez-vous qu'un appel synchrone va geler la page jusqu'à ce que la réponse soit reçue, de sorte qu'elle ne peut pas être utilisée dans un site de production, parce que les utilisateurs vont se fâcher si, pour une raison quelconque, ils doivent attendre 30 secondes avec leur navigateur gelé.

EDIT: ok, avec votre mise à jour c'est plus clair ce que vous voulez atteindre ;)

ainsi, votre code peut sembler comme 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);
            });
        });
    });

ainsi, 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
répondu FWH 2009-07-20 03:54:09
1
répondu llamerr 2011-04-26 14:54:21

les appels synchrones ne sont pas nécessairement plus lents, si vous avez une application où les appels AJAX s'ouvrent, postent, puis ferment une socket, les appels multiples à la socket n'ont pas de sens car certaines sockets ne peuvent gérer qu'une seule connexion, dans ce cas, la mise en file d'attente des données de sorte qu'elle ne soit envoyée que lorsque L'appel AJAX précédent est terminé signifie un débit de données beaucoup plus élevé.

0
répondu tomski777 2010-06-23 10:46:24
(async () => { 
  for(f of ['1.json','2.json','3.json']){
    var json = await $.getJSON(f);
    console.log(json)
 };
})()
  1. demandes 3 fichiers json avec jQuery, les appels ajax
  2. processus dans l'ordre (pas en parallèle) avec attendent
  3. fonctionne dans Chrome/Firefox/Edge (comme de 1/30/2018)

plus MDN

0
répondu Rm558 2018-01-30 06:25:32

Que Diriez-vous d'utiliser le noeud.js événements?

var EventEmitter = require('events').EventEmitter;
var eventEmitter = new EventEmitter();
var $ = require('jquery');

var doSomething = function (responseData) {
  var nextRequestData = {};
  // do something with responseData
  return nextRequestData;
};

// ajax requests
var request1 = $.ajax;
var request2 = $.ajax;
var requests = [request1, request2];

eventEmitter.on('next', function (i, requestData) {
  requests[i](requestData).then(
    function (responseData) {
      console.log(i, 'request completed');
      if (i+1 < requests.length) {
        var nextRequestData = doSomething(responseData);
        eventEmitter.emit('next', i+1, nextRequestData);
      }
      else {
        console.log('completed all requests');
      }
    },
    function () {
      console.log(i, 'request failed');
    }
  );
});

var data = {
  //data to send with request 1
};
eventEmitter.emit('next', 0, data);
-1
répondu tsknakamura 2015-07-05 03:30:41

séquentielle != synchrone, et je voudrais une solution asynchrone et séquentielle

l'exécution synchrone signifie généralement "utiliser la même horloge", tandis que l'exécution séquentielle signifie "suivre dans l'ordre ou la séquence".

pour votre cas d'utilisation spécifique, je pense que les deux conditions doivent être remplies, car l'exécution asynchrone implique la possibilité d'un résultat non séquentiel.

-1
répondu kamelkev 2016-06-18 00:53:52