Jakie są kolejki w jQuery?

387

Znalazłem dokument jQuery.com na queue()/ dequeue()jest zbyt prosty do zrozumienia. Czym dokładnie są kolejki w jQuery? Jak mam z nich korzystać?

jquerynewbie
źródło
3
Dobry przykład rozwiązania problemu z kolejką: stackoverflow.com/questions/5230333/…
gnarf

Odpowiedzi:

488

Zastosowania jQuery .queue()i.dequeue()

Kolejki w jQuery są używane do animacji. Możesz użyć ich do dowolnego celu. Są to tablica funkcji przechowywanych dla poszczególnych elementów, przy użyciu jQuery.data(). Są FIFO (First-In-First-Out). Możesz dodać funkcję do kolejki, wywołując .queue()i usuwając (wywołując) funkcje za pomocą .dequeue().

Aby zrozumieć wewnętrzne funkcje kolejki jQuery, czytanie źródła i przeglądanie przykładów ogromnie mi pomaga. Jednym z najlepszych przykładów funkcji kolejki, jakie widziałem, jest .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 );
  });
};

Domyślna kolejka - fx

Domyślna kolejka w jQuery to fx. Domyślna kolejka ma pewne specjalne właściwości, które nie są współużytkowane z innymi kolejkami.

  1. Auto Start: Dzwoniąc $(elem).queue(function(){});na fxkolejkę automatycznie dequeuenastępnej funkcji i uruchomić go, czy kolejka nie została uruchomiona.
  2. Wartownik „inprogress”: za każdym razem, gdy dequeue()pojawi się funkcja z fxkolejki, unshift()(ciągnie do pierwszej lokalizacji tablicy) ciąg znaków "inprogress"- co oznacza, że ​​kolejka jest aktualnie uruchomiona.
  3. To jest domyślne! fxKolejka jest wykorzystywane przez .animate()i wszystkie funkcje, które nazywają go domyślnie.

UWAGA: Jeśli korzystasz z niestandardowej kolejki, musisz ręcznie .dequeue()funkcje, nie uruchomią się automatycznie!

Pobieranie / ustawianie kolejki

Można pobrać odwołanie do kolejki jQuery, wywołując .queue()bez argumentu funkcji. Możesz użyć tej metody, jeśli chcesz zobaczyć, ile elementów znajduje się w kolejce. Można użyć push, pop, unshift, shiftmanipulować kolejkę na miejscu. Możesz zastąpić całą kolejkę, przekazując tablicę do .queue()funkcji.

Szybkie przykłady:

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

Przykład fxkolejki animacji ( ):

Uruchom przykład na 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);
});

Kolejny niestandardowy przykład kolejki

Uruchom przykład na 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');

Kolejkowanie połączeń Ajax:

I opracowała $.ajaxQueue()plugin, który używa $.Deferred, .queue()i $.ajax()również przejść z powrotem do obietnicy , że jest rozstrzygnięty, jeśli ukończone, prośba. Inna wersja $.ajaxQueuetego nadal działa w wersji 1.4 jest opublikowana w mojej odpowiedzi na sekwencjonowanie żądań Ajax

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

Dodałem to teraz jako artykuł na learn.jquery.com , są tam inne świetne artykuły na temat kolejek, patrz.

gnarf
źródło
+1. Pracuję nad skryptem użytkownika opartym na jQuery, który musi połączyć się ze skryptem PHP, tak jakby to był inny skrypt PHP działający na kliencie - jedno żądanie HTTP / inna operacja na raz, więc na pewno będzie to pomocne. Tylko pytanie: jQuery wymaga, aby kolejki były dołączane do obiektów, prawda? Którego obiektu powinienem użyć? $(window)?
PleaseStand
3
@idealmachine - Jak widać na przykładzie kolejki Ajax, można faktycznie dołączyć zdarzenia kolejki do pustego obiektu:$({})
gnarf
3
To podsumowanie jest niezwykle przydatne. Właśnie skończyłem budować leniwy moduł ładujący opóźniający żądanie dużej zawartości poniżej dolnej części ekranu, dopóki nie zostanie przewinięty do widoku. Użycie jQuery's queue () sprawiło, że żądania Ajax były bardzo płynne (nawet jeśli przejdziesz bezpośrednio na dół strony). Dzięki!
Jeff Standen,
14
Miło jest dowiedzieć się, że nadal aktualizujesz to dla nowszych wersji jQuery. +1 :)
Shaz
3
Aby dodać jedną rzecz dla tych, którzy dopiero uczą się kolejek i obietnic itp. - w przykładzie ajaxQueue wywołanie $ .ajaxQueue (), do którego wstawiasz żądanie ajax, które chcesz umieścić w kolejce wewnątrz (), zwróci obietnicę. Sposób, w jaki czekasz, aż kolejka będzie pusta, odbywa się za pośrednictwem promise.done (function () {alert ("done")}); Zajęło mi to godzinę, aby to znaleźć, więc mam nadzieję, że pomoże to komuś innemu uratować ich godzinę!
Ross
42

Aby zrozumieć metodę kolejki, musisz zrozumieć, w jaki sposób jQuery wykonuje animację. Jeśli napiszesz wiele wywołań metod ożywionych jeden po drugim, jQuery tworzy kolejkę „wewnętrzną” i dodaje do niej wywołania metod. Następnie uruchamia te animowane połączenia jeden po drugim.

Rozważ następujący kod.

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

Metoda „kolejka” / „dequeue” daje kontrolę nad tą „kolejką animacji”.

Domyślnie kolejka animacji nosi nazwę „FX”. Utworzyłem tutaj przykładową stronę z różnymi przykładami, które zilustrują sposób użycia metody kolejki.

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

Kod powyższej przykładowej strony:

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

Teraz możesz zapytać, dlaczego miałbym zawracać sobie głowę tą kolejką? Zwykle nie. Ale jeśli masz skomplikowaną sekwencję animacji, którą chcesz kontrolować, to metody kolejek / odwrotów są twoim przyjacielem.

Zobacz także tę interesującą rozmowę na grupie jQuery o tworzeniu skomplikowanej sekwencji animacji.

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

Demo animacji:

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

Daj mi znać, jeśli nadal masz pytania.

SolutionYogi
źródło
20

Animacja wielu obiektów w kolejce

Oto prosty przykład animacji wielu obiektów w kolejce.

Jquery pozwala nam tworzyć kolejki tylko dla jednego obiektu. Ale w ramach funkcji animacji możemy uzyskać dostęp do innych obiektów. W tym przykładzie budujemy naszą kolejkę nad obiektem #q, animując obiekty # box1 i # box2.

Pomyśl o kolejce jako o szeregu funkcji. Możesz więc manipulować kolejką jako tablicą. Możesz manipulować kolejką za pomocą push, pop, unshift, shift. W tym przykładzie usuwamy ostatnią funkcję z kolejki animacji i wstawiamy na początku.

Po zakończeniu uruchamiamy kolejkę animacji za pomocą funkcji dequeue ().

Zobacz w 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
źródło
15

Umożliwia kolejkowanie animacji ... na przykład zamiast tego

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

Który zanika element i sprawia, że szerokość 100 px w tym samym czasie . Korzystanie z kolejki umożliwia ustawianie animacji. Tak więc jeden kończy się po drugim.

$("#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();

Przykład z http://docs.jquery.com/Effects/queue

Alex
źródło
To nie jest poprawne. Gdy masz wiele wywołań „animowanych”, jQuery umieszcza je w kolejce, aby wykonać je jedna po drugiej. Korzystając z metody kolejki, możesz teraz uzyskać dostęp do tej kolejki i w razie potrzeby nią manipulować.
SolutionYogi
1
@SolutionYogi - Edytuj moją odpowiedź, jeśli uważasz, że jest niepoprawna - odpowiedź brzmi CW i masz wystarczającą liczbę powtórzeń.
alex
8

Ten wątek bardzo pomógł mi w moim problemie, ale użyłem $ .queue w inny sposób i pomyślałem, że opublikuję to, co wymyśliłem tutaj. Potrzebowałem sekwencji zdarzeń (ramek) do uruchomienia, ale sekwencję budowano dynamicznie. Mam zmienną liczbę symboli zastępczych, z których każdy powinien zawierać animowaną sekwencję obrazów. Dane są przechowywane w tablicy tablic, więc przeglądam tablice, aby zbudować każdą sekwencję dla każdego z symboli zastępczych w ten sposób:

/* 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');

Jest to uproszczona wersja skryptu, do którego dotarłem, ale powinna ona przedstawiać zasadę - gdy funkcja jest dodawana do kolejki, jest dodawana za pomocą konstruktora funkcji - w ten sposób funkcja może być zapisywana dynamicznie przy użyciu zmiennych z pętli ( s). Zwróć uwagę na sposób, w jaki funkcja jest przekazywana jako argument następnego wywołania (), i jest ona wywoływana na końcu. Funkcja w tym przypadku nie jest zależna od czasu (nie używa $ .fadeIn itp.), Więc przestawiam ramki za pomocą $ .delay.

bjorsq
źródło
$ .queue jest w zasadzie wypychaniem do tablicy przechowywanej w $ .data, dlatego musisz ręcznie nakazać jej wykonanie następnej funkcji za pomocą cb (); Czy moje rozumowanie jest prawidłowe?
eighteyes
-1

Funkcja makeRedi makeBlackwykorzystanie queueoraz dequeuewzajemne wykonywanie. Skutkuje to tym, że element „#wow” miga w sposób ciągły.

<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
źródło