¿Qué son las colas en jQuery?

387

Encontré el documento jQuery.com en queue() / dequeue()es demasiado simple de entender. ¿Qué son exactamente las colas en jQuery? ¿Cómo debo usarlos?

jquerynewbie
fuente
3
Un buen ejemplo de
cómo

Respuestas:

488

Los usos de jQuery .queue()y.dequeue()

Las colas en jQuery se usan para animaciones. Puede usarlos para cualquier propósito que desee. Son una matriz de funciones almacenadas por elemento, utilizando jQuery.data(). Son los primeros en entrar, primero en salir (FIFO). Puede agregar una función a la cola llamando .queue(), y elimina (llamando) las funciones usando.dequeue() .

Para comprender las funciones internas de la cola jQuery, leer la fuente y ver ejemplos me ayuda muchísimo. Uno de los mejores ejemplos de una función de cola que he visto es .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 cola predeterminada: fx

La cola predeterminada en jQuery es fx. La cola predeterminada tiene algunas propiedades especiales que no se comparten con otras colas.

  1. Inicio automático: al llamar a $(elem).queue(function(){});la fxcola, automáticamente se dequeueejecutará la siguiente función y se ejecutará si la cola no se ha iniciado.
  2. centinela 'en progreso': cada vez que realicedequeue() una función desde la fxcola, unshift()(empujará a la primera ubicación de la matriz) la cadena "inprogress", lo que indica que la cola se está ejecutando actualmente.
  3. ¡Es el predeterminado! La fxcola es utilizada por .animate()y todas las funciones que la llaman por defecto.

NOTA: Si está utilizando una cola personalizada, debe .dequeue()activar manualmente las funciones, ¡no se iniciarán automáticamente!

Recuperando / Configurando la cola

Puede recuperar una referencia a una cola jQuery llamando .queue()sin un argumento de función. Puede usar el método si desea ver cuántos elementos hay en la cola. Se puede utilizar push, pop, unshift, shiftpara manipular la cola en su lugar. Puede reemplazar toda la cola pasando una matriz al.queue() función.

Ejemplos rápidos:

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

Una animación (fx ejemplo de cola de ):

Ejecutar ejemplo en 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);
});

Otro ejemplo de cola personalizada

Ejecutar ejemplo en 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');

Llamadas en cola Ajax:

Desarrollé un $.ajaxQueue()complemento que usa el $.Deferred, .queue()y $.ajax()también para transmitir una promesa que se resuelve cuando se completa la solicitud. Otra versión de $.ajaxQueueeso que todavía funciona en 1.4 está publicada en mi respuesta a 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);

Ahora he agregado esto como un artículo en learn.jquery.com , hay otros excelentes artículos en ese sitio sobre colas, ve a buscar.

Gnarf
fuente
+1. Estoy trabajando en un script de usuario basado en jQuery que necesita conectarse a un script PHP como si fuera otro script PHP que se ejecuta en el cliente: una solicitud HTTP / otra operación a la vez, por lo que esto definitivamente será útil. Solo una pregunta: jQuery requiere que las colas se unan a los objetos, ¿verdad? Entonces, ¿qué objeto debo usar? $(window)?
favor
3
@idealmachine: como se ve en el ejemplo de Ajax Queue, en realidad puede adjuntar eventos de cola a un objeto vacío:$({})
gnarf
3
Este resumen es increíblemente útil. Acabo de terminar de crear un cargador diferido para retrasar la solicitud de contenido pesado que está debajo de la parte inferior de la pantalla hasta que se visualice. El uso de la cola de jQuery () hizo que esas solicitudes de Ajax fueran muy fluidas (incluso si saltas directamente al final de la página). ¡Gracias!
Jeff Standen
14
Es bueno saber que todavía está actualizando esto para las versiones más nuevas de jQuery. +1 :)
Shaz
3
Para agregar una cosa para aquellos que solo están aprendiendo colas y promesas, etc., en el ejemplo de ajaxQueue, la llamada a $ .ajaxQueue () a la que coloca su solicitud de ajax que desea hacer cola dentro de () devolverá una promesa. La forma en que espera hasta que la cola esté vacía es a través de promise.done (function () {alert ("done")}) ;. Me tomó una hora encontrar esto, ¡así que espero que esto ayude a alguien más a salvar su hora!
Ross
42

Para comprender el método de la cola, debe comprender cómo jQuery realiza la animación. Si escribe varias llamadas a métodos animados uno tras otro, jQuery crea una cola 'interna' y le agrega estas llamadas a métodos. Luego ejecuta esas llamadas animadas una por una.

Considere seguir el código.

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

El método 'cola' / 'cola' le da control sobre esta 'cola de animación'.

Por defecto, la cola de animación se llama 'fx'. He creado una página de muestra aquí que tiene varios ejemplos que ilustrarán cómo se podría usar el método de la cola.

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

Código para la página de muestra anterior:

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

Ahora puede preguntar, ¿por qué debería molestarme con esta cola? Normalmente no lo harás. Pero si tiene una secuencia de animación complicada que desea controlar, entonces los métodos de cola / cola son su amigo.

También vea esta interesante conversación en el grupo jQuery sobre cómo crear una secuencia de animación complicada.

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

Demo de la animación:

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

Avísame si aún tienes preguntas.

SolutionYogi
fuente
20

Animación de múltiples objetos en una cola

Aquí hay un ejemplo simple de animación de múltiples objetos en una cola.

Jquery nos permite hacer cola sobre un solo objeto. Pero dentro de la función de animación podemos acceder a otros objetos. En este ejemplo construimos nuestra cola sobre el objeto #q mientras animamos los objetos # box1 y # box2.

Piense en la cola como un conjunto de funciones. Para que pueda manipular la cola como una matriz. Puede usar push, pop, unshift, shift para manipular la cola. En este ejemplo, eliminamos la última función de la cola de animación y la insertamos al principio.

Cuando terminamos, comenzamos la cola de animación mediante la función dequeue ().

Ver en 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
fuente
15

Le permite poner en cola animaciones ... por ejemplo, en lugar de esto

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

Lo que desvanece el elemento y hace que el ancho sea de 100 px al mismo tiempo . Usar la cola te permite organizar las animaciones. Entonces uno termina después del otro.

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

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

alex
fuente
Esto no es correcto. Cuando tiene múltiples llamadas 'animadas', jQuery las pone en una cola para ejecutarlas una por una. Usando el método de cola, ahora puede acceder a esa cola y manipularla, si es necesario.
SolutionYogi
1
@SolutionYogi: edite mi respuesta si considera que es incorrecta: la respuesta es CW y tiene suficiente representante.
alex
8

Este hilo me ayudó mucho con mi problema, pero he usado $ .queue de una manera diferente y pensé en publicar lo que se me ocurrió aquí. Lo que necesitaba era que se activara una secuencia de eventos (cuadros), pero que la secuencia se construyera dinámicamente. Tengo un número variable de marcadores de posición, cada uno de los cuales debe contener una secuencia animada de imágenes. Los datos se mantienen en una matriz de matrices, por lo que recorro las matrices para construir cada secuencia para cada uno de los marcadores de posición de esta manera:

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

Esta es una versión simplificada del script al que he llegado, pero debería mostrar el principio: cuando una función se agrega a la cola, se agrega usando el constructor de funciones, de esta manera la función se puede escribir dinámicamente usando variables del bucle ( s) Observe la forma en que se pasa la función al argumento para la llamada next (), y esto se invoca al final. La función en este caso no depende del tiempo (no usa $ .fadeIn ni nada por el estilo), por lo que escalón los marcos usando $ .delay.

bjorsq
fuente
$ .queue es básicamente un impulso a una matriz almacenada en $ .data, por lo que debe indicarle manualmente que ejecute la siguiente función con cb (); ¿Es correcto mi entendimiento?
eighteyes
-1

Función makeRedy makeBlackuso queuey dequeuepara ejecutarse mutuamente. El efecto es que, el elemento '#wow' parpadea continuamente.

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