Que sont les files d'attente dans jQuery?

387

J'ai trouvé le document jQuery.com sur queue()/ dequeue()est trop simple à comprendre. Que sont exactement les files d'attente dans jQuery? Comment dois-je les utiliser?

jquerynewbie
la source
3
Un bon exemple de résolution d'un problème avec une file d'attente: stackoverflow.com/questions/5230333/…
gnarf

Réponses:

488

Les utilisations de jQuery .queue()et.dequeue()

Les files d'attente dans jQuery sont utilisées pour les animations. Vous pouvez les utiliser pour n'importe quel but que vous aimez. Il s'agit d'un tableau de fonctions stockées élément par élément, à l'aide de jQuery.data(). Il s'agit du premier entré, premier sorti (FIFO). Vous pouvez ajouter une fonction à la file d'attente en appelant .queue(), et vous supprimez (en appelant) les fonctions en utilisant.dequeue() .

Pour comprendre les fonctions de la file d'attente jQuery interne, lire la source et regarder des exemples m'aide énormément. L'un des meilleurs exemples de fonction de file d'attente que j'ai vu est .delay():

$.fn.delay = function( time, type ) {
  time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;
  type = type || "fx";

  return this.queue( type, function() {
    var elem = this;
    setTimeout(function() {
      jQuery.dequeue( elem, type );
    }, time );
  });
};

La file d'attente par défaut - fx

La file d'attente par défaut dans jQuery est fx. La file d'attente par défaut possède certaines propriétés spéciales qui ne sont pas partagées avec d'autres files d'attente.

  1. Démarrage automatique: lors de l'appel de $(elem).queue(function(){});la fxfile d'attente sera automatiquementdequeue la fonction suivante exécutée et exécutée si la file d'attente n'a pas démarré.
  2. sentinelle `` inprogress '': chaque fois que vous utilisezdequeue() une fonction de la fxfile d'attente, elle unshift()(poussera dans le premier emplacement du tableau) la chaîne "inprogress"- qui signale que la file d'attente est en cours d'exécution.
  3. C'est le défaut! La fxfile d'attente est utilisée par .animate()et toutes les fonctions qui l'appellent par défaut.

REMARQUE: Si vous utilisez une file d'attente personnalisée, vous devez manuellement .dequeue()les fonctions, elles ne démarreront pas automatiquement!

Récupération / définition de la file d'attente

Vous pouvez récupérer une référence à une file d'attente jQuery en appelant .queue()sans argument de fonction. Vous pouvez utiliser la méthode si vous souhaitez voir le nombre d'éléments dans la file d'attente. Vous pouvez utiliser push, pop, unshift, shiftpour manipuler la file d' attente en place. Vous pouvez remplacer la file d'attente entière en passant un tableau à la.queue() fonction.

Exemples rapides:

// lets assume $elem is a jQuery object that points to some element we are animating.
var queue = $elem.queue();
// remove the last function from the animation queue.
var lastFunc = queue.pop(); 
// insert it at the beginning:    
queue.unshift(lastFunc);
// replace queue with the first three items in the queue
$elem.queue(queue.slice(0,3)); 

Un fxexemple de file d'attente animation ( ):

Exécuter l'exemple sur jsFiddle

$(function() {
    // lets do something with google maps:
    var $map = $("#map_canvas");
    var myLatlng = new google.maps.LatLng(-34.397, 150.644);
    var myOptions = {zoom: 8, center: myLatlng, mapTypeId: google.maps.MapTypeId.ROADMAP};
    var geocoder = new google.maps.Geocoder();
    var map = new google.maps.Map($map[0], myOptions);
    var resized = function() {
        // simple animation callback - let maps know we resized
        google.maps.event.trigger(map, 'resize');
    };

    // wait 2 seconds
    $map.delay(2000);
    // resize the div:
    $map.animate({
        width: 250,
        height: 250,
        marginLeft: 250,
        marginTop:250
    }, resized);
    // geocode something
    $map.queue(function(next) {
        // find stackoverflow's whois address:
      geocoder.geocode({'address': '55 Broadway New York NY 10006'},handleResponse);

      function handleResponse(results, status) {
          if (status == google.maps.GeocoderStatus.OK) {
              var location = results[0].geometry.location;
              map.setZoom(13);
              map.setCenter(location);
              new google.maps.Marker({ map: map, position: location });
          }
          // geocoder result returned, continue with animations:
          next();
      }
    });
    // after we find stack overflow, wait 3 more seconds
    $map.delay(3000);
    // and resize the map again
    $map.animate({
        width: 500,
        height: 500,
        marginLeft:0,
        marginTop: 0
    }, resized);
});

Un autre exemple de file d'attente personnalisée

Exécuter l'exemple sur jsFiddle

var theQueue = $({}); // jQuery on an empty object - a perfect queue holder

$.each([1,2,3],function(i, num) {
  // lets add some really simple functions to a queue:
  theQueue.queue('alerts', function(next) { 
    // show something, and if they hit "yes", run the next function.
    if (confirm('index:'+i+' = '+num+'\nRun the next function?')) {
      next();
    }
  }); 
});

// create a button to run the queue:
$("<button>", {
  text: 'Run Queue', 
  click: function() { 
    theQueue.dequeue('alerts'); 
  }
}).appendTo('body');

// create a button to show the length:
$("<button>", {
  text: 'Show Length', 
  click: function() { 
    alert(theQueue.queue('alerts').length); 
  }
}).appendTo('body');

Mise en file d'attente des appels Ajax:

J'ai développé un $.ajaxQueue()plug - in qui utilise $.Deferred, .queue()et $.ajax()de passer également de retour d' une promesse qui est résolu lorsque la demande finalise. Une autre version de $.ajaxQueuecela fonctionne toujours en 1.4 est publiée sur ma réponse à Sequencing Ajax Requests

/*
* jQuery.ajaxQueue - A queue for ajax requests
* 
* (c) 2011 Corey Frang
* Dual licensed under the MIT and GPL licenses.
*
* Requires jQuery 1.5+
*/ 
(function($) {

// jQuery on an empty object, we are going to use this as our Queue
var ajaxQueue = $({});

$.ajaxQueue = function( ajaxOpts ) {
    var jqXHR,
        dfd = $.Deferred(),
        promise = dfd.promise();

    // queue our ajax request
    ajaxQueue.queue( doRequest );

    // add the abort method
    promise.abort = function( statusText ) {

        // proxy abort to the jqXHR if it is active
        if ( jqXHR ) {
            return jqXHR.abort( statusText );
        }

        // if there wasn't already a jqXHR we need to remove from queue
        var queue = ajaxQueue.queue(),
            index = $.inArray( doRequest, queue );

        if ( index > -1 ) {
            queue.splice( index, 1 );
        }

        // and then reject the deferred
        dfd.rejectWith( ajaxOpts.context || ajaxOpts,
            [ promise, statusText, "" ] );

        return promise;
    };

    // run the actual query
    function doRequest( next ) {
        jqXHR = $.ajax( ajaxOpts )
            .done( dfd.resolve )
            .fail( dfd.reject )
            .then( next, next );
    }

    return promise;
};

})(jQuery);

J'ai maintenant ajouté cela en tant qu'article sur learn.jquery.com , il y a d'autres excellents articles sur ce site sur les files d'attente, allez voir.

gnarf
la source
+1. Je travaille sur un script utilisateur basé sur jQuery qui doit se connecter à un script PHP comme s'il s'agissait d'un autre script PHP exécuté sur le client - une requête HTTP / autre opération à la fois, donc cela sera certainement utile. Juste une question: jQuery nécessite que les files d'attente soient attachées aux objets, non? Alors, quel objet dois-je utiliser? $(window)?
PleaseStand
3
@idealmachine - Comme vu dans l'exemple Ajax Queue, vous pouvez réellement attacher des événements de file d'attente à un objet vide:$({})
gnarf
3
Ce résumé est incroyablement utile. Je viens de terminer la construction d'un chargeur paresseux pour retarder la demande de contenu lourd qui se trouve sous le bas de l'écran jusqu'à ce qu'il défile dans la vue. L'utilisation de la file d'attente () de jQuery a rendu ces requêtes Ajax très fluides (même si vous sautez directement au bas de la page). Merci!
Jeff Standen
14
C'est agréable de découvrir que vous mettez toujours à jour cela pour les nouvelles versions de jQuery. +1 :)
Shaz
3
Pour ajouter une chose pour ceux qui apprennent les files d'attente et les promesses, etc. - dans l'exemple ajaxQueue, l'appel à $ .ajaxQueue () auquel vous mettez votre demande ajax que vous souhaitez mettre en file d'attente à l'intérieur du () retournera une promesse. La façon dont vous attendez que la file d'attente soit vide se fait via promise.done (function () {alert ("done")}) ;. Il m'a fallu une heure pour le trouver, alors j'espère que cela aidera quelqu'un d'autre à sauver son heure!
Ross
42

Pour comprendre la méthode de la file d'attente, vous devez comprendre comment jQuery fait l'animation. Si vous écrivez plusieurs appels de méthode animés l'un après l'autre, jQuery crée une file d'attente «interne» et y ajoute ces appels de méthode. Il exécute ensuite ces appels animés un par un.

Pensez à suivre le code.

function nonStopAnimation()
{
    //These multiple animate calls are queued to run one after
    //the other by jQuery.
    //This is the reason that nonStopAnimation method will return immeidately
    //after queuing these calls. 
    $('#box').animate({ left: '+=500'}, 4000);
    $('#box').animate({ top: '+=500'}, 4000);
    $('#box').animate({ left: '-=500'}, 4000);

    //By calling the same function at the end of last animation, we can
    //create non stop animation. 
    $('#box').animate({ top: '-=500'}, 4000 , nonStopAnimation);
}

La méthode 'queue' / 'dequeue' vous permet de contrôler cette 'file d'attente d'animation'.

Par défaut, la file d'attente d'animation est nommée 'fx'. J'ai créé un exemple de page ici qui contient divers exemples qui illustreront comment la méthode de file d'attente pourrait être utilisée.

http://jsbin.com/zoluge/1/edit?html,output

Code de l'exemple de page ci-dessus:

$(document).ready(function() {
    $('#nonStopAnimation').click(nonStopAnimation);

    $('#stopAnimationQueue').click(function() {
        //By default all animation for particular 'selector'
        //are queued in queue named 'fx'.
        //By clearning that queue, you can stop the animation.
        $('#box').queue('fx', []);
    });

    $('#addAnimation').click(function() {
        $('#box').queue(function() {
            $(this).animate({ height : '-=25'}, 2000);
            //De-queue our newly queued function so that queues
            //can keep running.
            $(this).dequeue();
        });
    });

    $('#stopAnimation').click(function() {
        $('#box').stop();
    });

    setInterval(function() {
        $('#currentQueueLength').html(
         'Current Animation Queue Length for #box ' + 
          $('#box').queue('fx').length
        );
    }, 2000);
});

function nonStopAnimation()
{
    //These multiple animate calls are queued to run one after
    //the other by jQuery.
    $('#box').animate({ left: '+=500'}, 4000);
    $('#box').animate({ top: '+=500'}, 4000);
    $('#box').animate({ left: '-=500'}, 4000);
    $('#box').animate({ top: '-=500'}, 4000, nonStopAnimation);
}

Maintenant, vous pouvez demander, pourquoi devrais-je me soucier de cette file d'attente? Normalement, vous ne le ferez pas. Mais si vous avez une séquence d'animation compliquée que vous souhaitez contrôler, les méthodes de file d'attente / de retrait sont votre ami.

Voir également cette conversation intéressante sur le groupe jQuery sur la création d'une séquence d'animation compliquée.

http://groups.google.com/group/jquery-en/browse_thread/thread/b398ad505a9b0512/f4f3e841eab5f5a2?lnk=gst

Démo de l'animation:

http://www.exfer.net/test/jquery/tabslide/

Faites-moi savoir si vous avez encore des questions.

SolutionYogi
la source
20

Animation de plusieurs objets dans une file d'attente

Voici un exemple simple d'animation d'objets multiples dans une file d'attente.

Jquery nous permet de faire la queue sur un seul objet. Mais dans la fonction d'animation, nous pouvons accéder à d'autres objets. Dans cet exemple, nous construisons notre file d'attente sur l'objet #q tout en animant les objets # box1 et # box2.

Considérez la file d'attente comme un tableau de fonctions. Vous pouvez donc manipuler la file d'attente comme un tableau. Vous pouvez utiliser push, pop, unshift, shift pour manipuler la file d'attente. Dans cet exemple, nous supprimons la dernière fonction de la file d'attente d'animation et l'insérons au début.

Lorsque nous avons terminé, nous démarrons la file d'attente d'animation par la fonction dequeue ().

Voir sur jsFiddle

html:

  <button id="show">Start Animation Queue</button>
  <p></p>
  <div id="box1"></div>
  <div id="box2"></div>
  <div id="q"></div>

js:

$(function(){

 $('#q').queue('chain',function(next){  
      $("#box2").show("slow", next);
  });


  $('#q').queue('chain',function(next){  
      $('#box1').animate(
          {left: 60}, {duration:1000, queue:false, complete: next}
      )
  });    


  $('#q').queue('chain',function(next){  
      $("#box1").animate({top:'200'},1500, next);
  });


  $('#q').queue('chain',function(next){  
      $("#box2").animate({top:'200'},1500, next);
  });


  $('#q').queue('chain',function(next){  
      $("#box2").animate({left:'200'},1500, next);
  });

  //notice that show effect comes last
  $('#q').queue('chain',function(next){  
      $("#box1").show("slow", next);
  });

});

$("#show").click(function () {
    $("p").text("Queue length is: " + $('#q').queue("chain").length);

    // remove the last function from the animation queue.
    var lastFunc = $('#q').queue("chain").pop();
    // insert it at the beginning:    
    $('#q').queue("chain").unshift(lastFunc);

    //start animation queue
    $('#q').dequeue('chain');
});

css:

        #box1 { margin:3px; width:40px; height:40px;
                position:absolute; left:10px; top:60px; 
                background:green; display: none; }
        #box2 { margin:3px; width:40px; height:40px;
                position:absolute; left:100px; top:60px; 
                background:red; display: none; }
        p { color:red; }  
enf644
la source
15

Il vous permet de mettre en file d'attente des animations ... par exemple, au lieu de cela

$('#my-element').animate( { opacity: 0.2, width: '100px' }, 2000);

Ce qui atténue l'élément et rend la largeur de 100 px en même temps . L'utilisation de la file d'attente vous permet de mettre en scène les animations. Donc, l'un finit après l'autre.

$("#show").click(function () {
    var n = $("div").queue("fx");
    $("span").text("Queue length is: " + n.length);
});

function runIt() {
    $("div").show("slow");
    $("div").animate({left:'+=200'},2000);
    $("div").slideToggle(1000);
    $("div").slideToggle("fast");
    $("div").animate({left:'-=200'},1500);
    $("div").hide("slow");
    $("div").show(1200);
    $("div").slideUp("normal", runIt);
}
runIt();

Exemple de http://docs.jquery.com/Effects/queue

alex
la source
Ce n'est pas correct. Lorsque vous avez plusieurs appels «animés», jQuery les place dans une file d'attente pour les exécuter un par un. En utilisant la méthode de la file d'attente, vous pouvez maintenant accéder à cette file d'attente et la manipuler, si nécessaire.
SolutionYogi
1
@SolutionYogi - Veuillez modifier ma réponse si vous pensez qu'elle est incorrecte - la réponse est CW'd et vous avez assez de représentants.
alex
8

Ce fil m'a beaucoup aidé avec mon problème, mais j'ai utilisé $ .queue d'une manière différente et j'ai pensé publier ce que j'ai trouvé ici. Ce dont j'avais besoin était une séquence d'événements (images) à déclencher, mais la séquence à construire dynamiquement. J'ai un nombre variable d'espaces réservés, dont chacun doit contenir une séquence animée d'images. Les données sont conservées dans un tableau de tableaux, donc je passe en revue les tableaux pour créer chaque séquence pour chacun des espaces réservés comme ceci:

/* create an empty queue */
var theQueue = $({});
/* loop through the data array */
for (var i = 0; i < ph.length; i++) {
    for (var l = 0; l < ph[i].length; l++) {
        /* create a function which swaps an image, and calls the next function in the queue */
        theQueue.queue("anim", new Function("cb", "$('ph_"+i+"' img').attr('src', '/images/"+i+"/"+l+".png');cb();"));
        /* set the animation speed */
        theQueue.delay(200,'anim');
    }
}
/* start the animation */
theQueue.dequeue('anim');

Il s'agit d'une version simplifiée du script auquel je suis arrivé, mais devrait montrer le principe - lorsqu'une fonction est ajoutée à la file d'attente, elle est ajoutée à l'aide du constructeur Function - de cette façon, la fonction peut être écrite dynamiquement à l'aide de variables de la boucle ( s). Notez la façon dont la fonction est passée l'argument pour le prochain appel (), et cela est invoqué à la fin. Dans ce cas, la fonction n'a pas de dépendance temporelle (elle n'utilise pas $ .fadeIn ou quelque chose comme ça), donc j'échelonne les images en utilisant $ .delay.

bjorsq
la source
$ .queue est essentiellement une poussée vers un tableau stocké dans $ .data, c'est pourquoi vous devez lui dire manuellement d'exécuter la fonction suivante avec le cb (); Ma compréhension est-elle correcte?
eighteyes
-1

Fonctionner makeRedet makeBlackutiliser queueet dequeues'exécuter mutuellement. L'effet est que l'élément '#wow' clignote en continu.

<html>
  <head>
    <script src="http://code.jquery.com/jquery-1.9.1.js"></script>
    <script type="text/javascript">
      $(document).ready(function(){
          $('#wow').click(function(){
            $(this).delay(200).queue(makeRed);
            });
          });

      function makeRed(){
        $('#wow').css('color', 'red');
        $('#wow').delay(200).queue(makeBlack);
        $('#wow').dequeue();
      }

      function makeBlack(){
        $('#wow').css('color', 'black');
        $('#wow').delay(200).queue(makeRed);
        $('#wow').dequeue();
      }
    </script>
  </head>
  <body>
    <div id="wow"><p>wow</p></div>
  </body>
</html>
ardsrk
la source