59 votes

File d'attente des requêtes ajax à l'aide de jQuery.la file d'attente()

Je suis à l'aide de jQuery.file() pour la première fois et n'ont pas vraiment pris. Quelqu'un pourrait s'il vous plaît signaler ce que je fais de mal?

En regardant dans firebug, je vois toujours mon POST demandes de tir en même temps donc je me demande si je vais appeler dequeue() dans le mauvais endroit.

Aussi - comment puis-je obtenir la longueur de la file? Merci!

La raison que j'ai besoin de faire la queue à ces demandes est qu'il obtient le feu sur clic d'un bouton. Et son possible pour l'utilisateur à cliquer sur plusieurs boutons en succession rapide.

Essayé de supprimer la base de la structure de mon code:

$("a.button").click(function(){
   $(this).doAjax(params);
});

// method
doAjax:function(params){ 

   $(document).queue("myQueueName", function(){
     $.ajax({
       type: 'POST',
       url: 'whatever.html',
       params: params,
       success: function(data){
         doStuff;

         $(document).dequeue("myQueueName");
       }
     });
   });

}

Merci d'avance pour toute aide.

96voto

jAndy Points 93076

Vous problème ici est qu' .ajax() déclenche un système exécutant une requête Ajax. Cela signifie que, .ajax() retourne immédiatement, sans blocage. Si votre file d'attente de l'fonctions, mais ils feront feu presque en même temps, comme vous l'avez décrit.

Je ne pense pas que l' .queue() est un bon endroit pour faire des requêtes ajax, c'est plus destiné pour l'utilisation de l' fx methods. Vous avez besoin d'un simple gestionnaire.

var ajaxManager = (function() {
     var requests = [];

     return {
        addReq:  function(opt) {
            requests.push(opt);
        },
        removeReq:  function(opt) {
            if( $.inArray(opt, requests) > -1 )
                requests.splice($.inArray(opt, requests), 1);
        },
        run: function() {
            var self = this,
                oriSuc;

            if( requests.length ) {
                oriSuc = requests[0].complete;

                requests[0].complete = function() {
                     if( typeof(oriSuc) === 'function' ) oriSuc();
                     requests.shift();
                     self.run.apply(self, []);
                };   

                $.ajax(requests[0]);
            } else {
              self.tid = setTimeout(function() {
                 self.run.apply(self, []);
              }, 1000);
            }
        },
        stop:  function() {
            requests = [];
            clearTimeout(this.tid);
        }
     };
}());

C'est loin d'être parfaite, je veux juste démontrer que le chemin à parcourir. L'exemple ci-dessus pourrait être utilisé comme

$(function() {
    ajaxManager.run(); 

    $("a.button").click(function(){
       ajaxManager.addReq({
           type: 'POST',
           url: 'whatever.html',
           data: params,
           success: function(data){
              // do stuff
           }
       });
    });
});

13voto

diggersworld Points 5051

J'avais besoin de faire quelque chose de similaire donc pensé que je poste ma solution ici.

Fondamentalement, ce que j'ai est une page qui répertorie les projets sur des étagères qui tous ont des critères. J'ai voulu charger les rayons un par un plutôt que pour obtenir du contenu à l'utilisateur plus rapide qui ils pouvaient regarder, tandis que le reste de la charge.

Fondamentalement, je stocke l'ID de chaque étagère dans un tableau JS que j'utilise lors de l'appel de PHP.

Ensuite, j'ai créé une fonction récursive qui apparaît le premier indice du tableau à chaque fois son nom et à la demande de l'étagère pour le sauté id. Une fois que j'ai la réponse de l' $.get() ou $.post() selon la, je préfère utiliser je puis appeler la fonction récursive à partir de l'intérieur de la fonction de rappel.

Voici une élaboration dans le code:

// array of shelf IDs
var shelves = new Array(1,2,3,4);

// the recursive function
function getShelfRecursive() {

    // terminate if array exhausted
    if (shelves.length === 0)
        return;

    // pop top value
    var id = shelves[0];
    shelves.shift();

    // ajax request
    $.get('/get/shelf/' + id, function(){
         // call completed - so start next request
         getShelfRecursive();
    });
}

// fires off the first call
getShelfRecursive();

7voto

David Woakes Points 71

J'avais besoin de faire cela pour un nombre inconnu d'appels ajax. La réponse a été de pousser chacun dans un tableau et ensuite utiliser:

$.when.apply($, arrayOfDeferreds).done(function () {
    alert("All done");
});

7voto

Guy Bedford Points 253

J'ai trouvé les solutions ci-dessus un peu compliqués, plus j'ai besoin de modifier la demande juste avant de l'envoyer (la mise à jour de nouvelles données jeton).

Alors j'ai mis ce un ensemble - https://gist.github.com/2470554

0voto

Pow-Ian Points 2677

J'ai également eu à le faire au sein d'une solution que j'ai eu et j'ai trouvé que je pouvais le faire de cette façon:

//A variable for making sure to wait for multiple clicks before emptying.
var waitingTimeout; 

$("a.button").click(function(){
   $(this).doAjax(params);
   clearTimeout(waitingTimeout);
   waitingTimeout = setTimeout(function(){noMoreClicks();},1000);
});

// method
doAjax:function(params){ 

   $(document).queue("myQueueName", function(next){
     $.ajax({
       type: 'POST',
       url: 'whatever.html',
       data: params,
       contentType: "application/json; charset=utf-8",
       dataType: "json",
       success: function(data){
         doStuff;
         next();
       },
       failure: function(data){
         next();
       },
       error: function(data){
         next();
       }
     });
   });

}

function noMoreClicks(){
    $(document).dequeue("myQueueName");
}

en utilisant l' next() de callback qui est passé dans la file d'attente de fonction, vous pouvez retirer de l'opération suivante. Donc en les mettant ensuite, les gestionnaires de l'ajax, vous pouvez effectivement faire les appels ajax asynchrone pour le navigateur et le rendu ou de la peinture au fil de l'navigateur, mais de les rendre synchrone ou sérialisé les uns aux autres.

Voici un exemple de base. Dans l'exemple de violon. Cliquez sur le bouton une fois et attendre une seconde. Vous verrez que le temps de déclencheurs et de la seule opération qui se passe. Ensuite, cliquez sur le bouton aussi vite que vous le pouvez (ou plus rapide qu'une seconde) et vous verrez que toutes les fois que vous cliquez sur le bouton, les opérations sont mises en file d'attente, puis seulement après une attente d'une seconde, ils ont frappé la page et à la décoloration, l'un après l'autre.

La beauté de ceci est que si la file d'attente est déjà vidange, toutes les opérations que vous ajoutez à ça alors que c'est la vidange sont placés sur la fin et puis juste transformé le moment venu.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X