O que são filas no jQuery?

387

Eu achei o documento jQuery.com em queue()/ dequeue()é muito simples de entender. O que exatamente são as filas no jQuery? Como devo usá-los?

jquerynewbie
fonte
3
Um bom exemplo de resolver um problema com uma fila: stackoverflow.com/questions/5230333/...
gnarf

Respostas:

488

Os usos do jQuery .queue()e.dequeue()

Filas no jQuery são usadas para animações. Você pode usá-los para qualquer finalidade que desejar. Eles são uma matriz de funções armazenadas por elemento, usando jQuery.data(). Eles são o primeiro a entrar, primeiro a sair (FIFO). Você pode adicionar uma função à fila chamando .queue()e remover (chamando) as funções usando .dequeue().

Para entender as funções internas da fila jQuery, ler a fonte e ver exemplos me ajuda tremendamente. Um dos melhores exemplos de uma função de fila que eu já vi é .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 );
  });
};

A fila padrão - fx

A fila padrão no jQuery é fx. A fila padrão possui algumas propriedades especiais que não são compartilhadas com outras filas.

  1. Início automático: ao chamar $(elem).queue(function(){});a fxfila, dequeuea próxima função será automaticamente executada, se a fila não tiver iniciado.
  2. Sentinela 'inprogress': sempre que dequeue()uma função da fxfila, ela unshift()(envia para o primeiro local da matriz) a string "inprogress"- que indica que a fila está sendo executada no momento.
  3. É o padrão! A fxfila é usada por .animate()e todas as funções que a chamam por padrão.

NOTA: Se você estiver usando uma fila personalizada, deverá executar manualmente .dequeue()as funções, pois elas não serão iniciadas automaticamente!

Recuperando / configurando a fila

Você pode recuperar uma referência a uma fila jQuery chamando .queue()sem um argumento de função. Você pode usar o método se desejar ver quantos itens estão na fila. Você pode usar push, pop, unshift, shiftpara manipular a fila no lugar. Você pode substituir a fila inteira passando uma matriz para a .queue()função.

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

Um fxexemplo de fila animation ( ):

Executar exemplo no 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);
});

Outro exemplo de fila personalizada

Executar exemplo no 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');

Filas de chamadas Ajax:

Eu desenvolvi um $.ajaxQueue()plug - in que usa o $.Deferred, .queue()e $.ajax()também para devolver uma promessa que é resolvida quando a solicitação é concluída. Outra versão do $.ajaxQueueque ainda funciona na versão 1.4 está publicada na minha resposta para Sequenciar pedidos de 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);

Agora adicionei isso como um artigo em learn.jquery.com , há outros ótimos artigos nesse site sobre filas, veja.

gnarf
fonte
+1. Estou trabalhando em um script de usuário baseado em jQuery que precisa se conectar a um script PHP como se fosse outro script PHP em execução no cliente - uma solicitação HTTP / outra operação por vez, então isso definitivamente será útil. Apenas uma pergunta: o jQuery exige que as filas sejam anexadas aos objetos, certo? Então, qual objeto devo usar? $(window)?
PleaseStand
3
@idealmachine - Como visto no exemplo da fila do Ajax, você pode realmente anexar eventos da fila a um objeto vazio:$({})
gnarf
3
Este resumo é incrivelmente útil. Acabei de criar um carregador lento para atrasar a solicitação de conteúdo pesado que fica abaixo da parte inferior da tela até que seja rolado para exibição. O uso da fila do jQuery () tornou essas solicitações do Ajax muito fáceis (mesmo que você pule diretamente para o final da página). Obrigado!
Jeff Standen
14
É bom descobrir que você ainda está atualizando isso para versões mais recentes do jQuery. +1 :)
Shaz 26/06
3
Para adicionar uma coisa para aqueles que estão apenas aprendendo filas e promessas, etc - no exemplo ajaxQueue, a chamada para $ .ajaxQueue () na qual você coloca a solicitação ajax que deseja enfileirar dentro de () retornará uma promessa. A maneira como você espera até que a fila esteja vazia é através de promessa.done (função () {alerta ("pronto")}) ;. Levei uma hora para encontrar isso, então espero que isso ajude alguém a salvar sua hora!
28412 Ross
42

Para entender o método da fila, você precisa entender como o jQuery faz animação. Se você escrever várias chamadas de método de animação uma após a outra, o jQuery criará uma fila 'interna' e adicionará essas chamadas de método. Em seguida, executa essas chamadas animadas uma a uma.

Considere o seguinte 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);
}

O método 'fila' / 'desenfileirar' fornece controle sobre essa 'fila de animação'.

Por padrão, a fila de animação é denominada 'fx'. Eu criei uma página de amostra aqui que tem vários exemplos que ilustrarão como o método de fila pode ser usado.

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

Código para a página de exemplo acima:

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

Agora você pode perguntar, por que eu deveria me preocupar com essa fila? Normalmente você não. Mas se você tem uma sequência de animação complicada que deseja controlar, os métodos de fila / desenfileiramento são seus amigos.

Veja também esta interessante conversa no grupo jQuery sobre a criação de uma sequência de animação complicada.

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

Demonstração da animação:

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

Deixe-me saber se você ainda tiver dúvidas.

SolutionYogi
fonte
20

Animação de vários objetos em uma fila

Aqui está um exemplo simples de animação de vários objetos em uma fila.

Jquery nos permite fazer fila sobre apenas um objeto. Mas dentro da função de animação, podemos acessar outros objetos. Neste exemplo, construímos nossa fila sobre o objeto # q enquanto animamos os objetos # box1 e # box2.

Pense na fila como uma matriz de funções. Então você pode manipular a fila como uma matriz. Você pode usar push, pop, unshift, shift para manipular a fila. Neste exemplo, removemos a última função da fila de animação e a inserimos no início.

Quando terminamos, iniciamos a fila de animação pela função dequeue ().

Veja em 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
fonte
15

Permite enfileirar animações ... por exemplo, em vez disso

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

O que diminui o elemento e aumenta a largura de 100 px ao mesmo tempo . O uso da fila permite preparar as animações. Então, um termina após o outro.

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

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

alex
fonte
Isso não está correto. Quando você tem várias chamadas 'animadas', o jQuery as coloca em uma fila para executá-las uma a uma. Usando o método da fila, agora você pode acessar essa fila e manipulá-la, se necessário.
SolutionYogi
11
@SolutionYogi - Edite minha resposta se achar que está incorreta - a resposta é CW'd e você tem representante suficiente.
alex
8

Esse tópico me ajudou muito com o meu problema, mas eu usei o $ .queue de uma maneira diferente e pensei em publicar o que descobri aqui. O que eu precisava era de uma sequência de eventos (quadros) a ser acionada, mas a sequência a ser construída dinamicamente. Eu tenho um número variável de espaços reservados, cada um dos quais deve conter uma sequência animada de imagens. Os dados são mantidos em uma matriz de matrizes, então eu percorro as matrizes para criar cada sequência para cada um dos espaços reservados como este:

/* 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 é uma versão simplificada do script que cheguei, mas deve mostrar o princípio - quando uma função é adicionada à fila, é adicionada usando o construtor Function - dessa maneira, a função pode ser escrita dinamicamente usando variáveis ​​do loop ( s) Observe como a função é passada no argumento para a próxima chamada (), e isso é chamado no final. A função neste caso não tem dependência de tempo (não usa $ .fadeIn ou algo parecido), então eu alterno os quadros usando $ .delay.

bjorsq
fonte
$ .queue é basicamente um push para uma matriz armazenada em $ .data, e é por isso que você precisa dizer manualmente para executar a próxima função com o cb (); Meu entendimento está correto?
eighteyes
-1

Função makeRede makeBlackuso queuee dequeuepara executar um ao outro. O efeito é que, o elemento '#wow' pisca 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
fonte