Was sind Warteschlangen in jQuery?

387

Ich fand das jQuery.com-Dokument auf queue()/ dequeue()zu einfach zu verstehen. Was genau sind Warteschlangen in jQuery? Wie soll ich sie benutzen?

jquerynewbie
quelle
3
Ein gutes Beispiel für die Lösung eines Problems mit einer Warteschlange: stackoverflow.com/questions/5230333/…
Gnarf

Antworten:

488

Die Verwendung von jQuery .queue()und.dequeue()

Warteschlangen in jQuery werden für Animationen verwendet. Sie können sie für jeden gewünschten Zweck verwenden. Sie sind ein Array von Funktionen, die auf Elementbasis unter Verwendung von gespeichert werden jQuery.data(). Sie sind First-In-First-Out (FIFO). Sie können der Warteschlange eine Funktion hinzufügen, indem Sie aufrufen .queue(), und Sie entfernen (indem Sie die Funktionen aufrufen) mit .dequeue().

Das Verständnis der internen Funktionen der jQuery-Warteschlange, das Lesen der Quelle und das Betrachten von Beispielen helfen mir enorm. Eines der besten Beispiele für eine Warteschlangenfunktion, die ich gesehen habe, ist .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 );
  });
};

Die Standardwarteschlange - fx

Die Standardwarteschlange in jQuery ist fx. Die Standardwarteschlange verfügt über einige spezielle Eigenschaften, die nicht für andere Warteschlangen freigegeben sind.

  1. Automatischer Start: Beim Aufrufen $(elem).queue(function(){});der fxWarteschlange wird automatisch dequeuedie nächste Funktion ausgeführt und ausgeführt, wenn die Warteschlange noch nicht gestartet wurde.
  2. 'inprogress' Sentinel: Immer wenn Sie dequeue()eine Funktion aus der fxWarteschlange auswählen , wird unshift()die Zeichenfolge (an die erste Position des Arrays verschoben ) die Zeichenfolge anzeigen, die angibt,"inprogress" dass die Warteschlange gerade ausgeführt wird.
  3. Es ist die Standardeinstellung! Die fxWarteschlange wird von .animate()und allen Funktionen verwendet, die sie standardmäßig aufrufen.

HINWEIS: Wenn Sie eine benutzerdefinierte Warteschlange verwenden, müssen Sie .dequeue()die Funktionen manuell ausführen. Sie werden nicht automatisch gestartet!

Warteschlange abrufen / einstellen

Sie können einen Verweis auf eine jQuery-Warteschlange abrufen, indem Sie .queue()ohne Funktionsargument aufrufen . Sie können die Methode verwenden, wenn Sie sehen möchten, wie viele Elemente sich in der Warteschlange befinden. Sie können verwendet werden push, pop, unshift, shiftdie Warteschlange an Ort und Stelle zu manipulieren. Sie können die gesamte Warteschlange ersetzen, indem Sie ein Array an die .queue()Funktion übergeben.

Schnelle Beispiele:

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

Ein fxBeispiel für eine Animation ( ) -Warteschlange:

Führen Sie ein Beispiel auf jsFiddle aus

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

Ein weiteres Beispiel für eine benutzerdefinierte Warteschlange

Führen Sie ein Beispiel auf jsFiddle aus

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

Ajax-Anrufe in die Warteschlange stellen:

Ich habe ein $.ajaxQueue()Plugin entwickelt, das das $.Deferred, .queue()und verwendet, $.ajax()um auch ein Versprechen zurückzugeben , das gelöst wird, wenn die Anfrage abgeschlossen ist. Eine andere Version davon $.ajaxQueue, die noch in 1.4 funktioniert, ist in meiner Antwort auf Sequencing Ajax Requests veröffentlicht

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

Ich habe dies jetzt als Artikel auf learn.jquery.com hinzugefügt . Es gibt andere großartige Artikel auf dieser Website über Warteschlangen.

Zwerg
quelle
+1. Ich arbeite an einem jQuery-basierten Benutzerskript, das eine Verbindung zu einem PHP-Skript herstellen muss, als wäre es ein anderes PHP-Skript, das auf dem Client ausgeführt wird - jeweils eine HTTP-Anforderung / eine andere Operation. Dies ist also auf jeden Fall hilfreich. Nur eine Frage: Für jQuery müssen Warteschlangen an Objekte angehängt werden, oder? Welches Objekt soll ich also verwenden? $(window)?
PleaseStand
3
@idealmachine - Wie im Ajax Queue-Beispiel zu sehen, können Sie Warteschlangenereignisse tatsächlich an ein leeres Objekt anhängen:$({})
Gnarf
3
Diese Zusammenfassung ist unglaublich nützlich. Ich habe gerade einen Lazy Loader erstellt, um die Anforderung von umfangreichen Inhalten, die sich unter dem unteren Bildschirmrand befinden, zu verzögern, bis sie in die Ansicht gescrollt werden. Durch die Verwendung von jQuerys queue () wurden diese Ajax-Anforderungen sehr reibungslos (selbst wenn Sie direkt zum Ende der Seite springen). Vielen Dank!
Jeff Standen
14
Es ist schön herauszufinden, dass Sie dies für neuere Versionen von jQuery noch aktualisieren. +1 :)
Shaz
3
Um eine Sache für diejenigen hinzuzufügen, die nur Warteschlangen und Versprechen usw. lernen - im Beispiel ajaxQueue gibt der Aufruf von $ .ajaxQueue (), an den Sie Ihre Ajax-Anfrage stellen, die Sie innerhalb von () in die Warteschlange stellen möchten, ein Versprechen zurück. Sie warten, bis die Warteschlange leer ist, und versprechen dies. Ich habe eine Stunde gebraucht, um das zu finden, also hoffe, das hilft jemand anderem, seine Stunde zu retten!
Ross
42

Um die Warteschlangenmethode zu verstehen, müssen Sie verstehen, wie jQuery Animationen ausführt. Wenn Sie mehrere animierte Methodenaufrufe nacheinander schreiben, erstellt jQuery eine 'interne' Warteschlange und fügt diese Methodenaufrufe hinzu. Dann werden diese animierten Aufrufe einzeln ausgeführt.

Betrachten Sie den folgenden 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);
}

Mit der Methode 'queue' / 'dequeue' können Sie diese 'Animationswarteschlange' steuern.

Standardmäßig heißt die Animationswarteschlange 'fx'. Ich habe hier eine Beispielseite erstellt, die verschiedene Beispiele enthält, die veranschaulichen, wie die Warteschlangenmethode verwendet werden kann.

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

Code für die obige Beispielseite:

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

Nun fragen Sie sich vielleicht, warum ich mich mit dieser Warteschlange beschäftigen soll. Normalerweise wirst du nicht. Wenn Sie jedoch eine komplizierte Animationssequenz haben, die Sie steuern möchten, sind Warteschlangen- / Warteschlangenmethoden Ihr Freund.

Sehen Sie sich auch dieses interessante Gespräch in der jQuery-Gruppe über das Erstellen einer komplizierten Animationssequenz an.

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

Demo der Animation:

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

Lassen Sie mich wissen, wenn Sie noch Fragen haben.

SolutionYogi
quelle
20

Animation mehrerer Objekte in einer Warteschlange

Hier ist ein einfaches Beispiel für die Animation mehrerer Objekte in einer Warteschlange.

Mit Jquery können wir nur ein Objekt in die Warteschlange stellen. Innerhalb der Animationsfunktion können wir jedoch auf andere Objekte zugreifen. In diesem Beispiel erstellen wir unsere Warteschlange über dem Objekt #q, während wir die Objekte # box1 und # box2 animieren.

Stellen Sie sich die Warteschlange als eine Reihe von Funktionen vor. So können Sie die Warteschlange als Array bearbeiten. Sie können Push, Pop, Unhift und Shift verwenden, um die Warteschlange zu bearbeiten. In diesem Beispiel entfernen wir die letzte Funktion aus der Animationswarteschlange und fügen sie am Anfang ein.

Wenn wir fertig sind, starten wir die Animationswarteschlange mit der Funktion dequeue ().

Siehe bei 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
quelle
15

Sie können damit beispielsweise Animationen in die Warteschlange stellen

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

Welches das Element schwindet und macht die Breite 100 Pixel zur gleichen Zeit . Mit der Warteschlange können Sie die Animationen inszenieren. So endet einer nach dem anderen.

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

Beispiel von http://docs.jquery.com/Effects/queue

Alex
quelle
Das ist nicht richtig. Wenn Sie mehrere "animierte" Aufrufe haben, stellt jQuery diese in eine Warteschlange, um sie einzeln auszuführen. Mit der Warteschlangenmethode können Sie jetzt auf diese Warteschlange zugreifen und sie bei Bedarf bearbeiten.
SolutionYogi
1
@SolutionYogi - Bitte bearbeiten Sie meine Antwort, wenn Sie der Meinung sind, dass sie falsch ist. Die Antwort lautet CW'd und Sie haben genügend Wiederholungen.
Alex
8

Dieser Thread hat mir bei meinem Problem sehr geholfen, aber ich habe $ .queue anders verwendet und dachte, ich würde hier posten, was ich mir ausgedacht habe. Was ich brauchte, war eine Folge von Ereignissen (Frames), die ausgelöst werden sollten, aber die Folge, die dynamisch erstellt werden sollte. Ich habe eine variable Anzahl von Platzhaltern, von denen jeder eine animierte Folge von Bildern enthalten sollte. Die Daten werden in einem Array von Arrays gespeichert, daher durchlaufe ich die Arrays, um jede Sequenz für jeden der Platzhalter wie folgt zu erstellen:

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

Dies ist eine vereinfachte Version des Skripts, zu dem ich gelangt bin, das jedoch das Prinzip zeigen sollte: Wenn eine Funktion zur Warteschlange hinzugefügt wird, wird sie mithilfe des Funktionskonstruktors hinzugefügt. Auf diese Weise kann die Funktion mithilfe von Variablen aus der Schleife dynamisch geschrieben werden ( s). Beachten Sie, wie der Funktion das Argument für den nächsten () Aufruf übergeben wird und dieses am Ende aufgerufen wird. Die Funktion hat in diesem Fall keine Zeitabhängigkeit (sie verwendet kein $ .fadeIn oder ähnliches), daher versetze ich die Frames mit $ .delay.

bjorsq
quelle
$ .queue ist im Grunde ein Push für ein in $ .data gespeichertes Array, weshalb Sie es manuell anweisen müssen, die nächste Funktion mit cb () auszuführen. Ist mein Verständnis richtig?
Achtzehn Jahre
-1

Funktionieren makeRedund makeBlackverwenden queueund dequeuesich gegenseitig ausführen. Der Effekt ist, dass das Element '#wow' kontinuierlich blinkt.

<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
quelle