Experimenting With jQuery's Queue() And Dequeue() Methods

Posted March 2, 2010 at 9:10 AM by Ben Nadel

Tags: Javascript / DHTML

jQuery comes with a number of built-in animation methods like slideUp() and slideDown(). While these appear to be packaged in their own methods, many of them are powered internally by the animate() method. And while the animate() method handles many of the effects, a string of sequential animations is controlled internally by jQuery's queuing mechanism. This queuing mechanism, while used primarily for the FX ("effects") queue, is also made available as part of the jQuery API. This API allows programmers to manage arbitrary queues for anything that needs to happen sequentially.

 
 
 
 
 
 
 
 
 
 

I have never used the queuing mechanism before, so I thought I would do some experimentation. There are two main methods that control a particular queue: queue() and dequeue(). While these methods can be accessed off of the jQuery namespace, they are designed to be associated with a given element or object. So, you can think of a queue as not just a series of events, but rather as a series of events that take place in the context of a given object.

To add an action to a queue, you have to tell the queue() method the name of the queue (the default queue is the "fx" queue) and the callback to be executed as the queue item. jQuery does not have any insight into how the queue items function; as such, we need to explicitly tell jQuery when to move to the next item in the queue. This can be done in two ways: first, you can call the dequeue() method on the given element with the given queue name. This works, but requires you to use the queue name which becomes yet another data point to maintain over time. The second, more optimal way, is to use the next() function that jQuery passes to your queue item callback. The next() function encapsulates the dequeue() method and the queue name into a single point of execution.

While the jQuery "fx" animation queue starts to execute immediately (dequeues itself), explicitly managed queues do not. As such, after we build up our queue items, we have to call dequeue() on the queue in order to kick off the series of sequential events. To see this in action, I have set up a small test page:

  • <!DOCTYPE HTML>
  • <html>
  • <head>
  • <title>jQuery Queue And Dequeue</title>
  • <script type="text/javascript" src="../jquery-1.4.2.js"></script>
  • <script type="text/javascript">
  •  
  • // When the DOM is ready, initialize scripts.
  • jQuery(function( $ ){
  •  
  • // Get a handle on the paragraph we want to update.
  • var para = $( "p:first" );
  •  
  • // Add the first queue item. Unlike the native animation
  • // methods, manually created queue items don't start
  • // executing right away - we have to manually call the
  • // dequeue() method at the end.
  • para.queue(
  • "testQueue",
  • function( next ){
  • para.html( "This is queue item #1: Hot" );
  •  
  • // Each queue method is passed a "next" method
  • // reference. This method encapsulates the
  • // name of the queue into a function. This way
  • // we can dequeue the current queue without
  • // having to know its name.
  • next();
  • }
  • );
  •  
  • // Delay the queue for a bit.
  • para.delay( 1500, "testQueue" );
  •  
  • // Add the next queue item.
  • para.queue(
  • "testQueue",
  • function( next ){
  • para.html( "This is queue item #2: Sexy" );
  • next();
  • }
  • );
  •  
  • // Delay the queue for a bit.
  • para.delay( 1500, "testQueue" );
  •  
  • // Add the next queue item.
  • para.queue(
  • "testQueue",
  • function( next ){
  • para.html( "This is queue item #3: Sleezy" );
  • next();
  • }
  • );
  •  
  •  
  • // ---------------------------------------------- //
  •  
  •  
  • // When we have our queue set up, we have to manually
  • // dequeue the first item to get the queue to start
  • // processing.
  • para.dequeue( "testQueue" );
  •  
  • });
  •  
  • </script>
  • </head>
  • <body>
  •  
  • <h1>
  • jQuery Queue And Dequeue
  • </h1>
  •  
  • <p>
  • This is where the queue output will go.
  • </p>
  •  
  • </body>
  • </html>

As you can see, I am using both the queue() method and the delay() method to build up my, "testQueue", queue. The delay() method, while typically used with animation queues, can be used to add an arbitrary pause to any queue event series. Once I have built up the queue, I use the dequeue() method to kick off the queue events.

jQuery's queuing mechanism seems very cool but, I am not sure what I would use it for outside of the native animation methods. I would certainly love to hear how other people might leverage this functionality.


You Might Also Be Interested In:



Reader Comments

Mar 2, 2010 at 9:47 AM // reply »
19 Comments

It's especially useful when have a series of asynchronous method calls that you want to execute serially, and don't want to maintain a chain of callbacks.

Say you want to execute first_async_action() followed by second_async_action(), followed by third_async_action(). You could do this:

<pre>
first_async_action(function(){
second_async_action(function(){
third_async_action(function(){
alert( 'done!' );
});
});
});
</pre>

Or if that looks messy (which it does) you could try something like this:

<pre>
function start(){
first_async_action( exec_second_async_action );
};

function exec_second_async_action(){
second_async_action( exec_third_async_action );
};

function exec_third_async_action(){
third_async_action( all_done );
};

function all_done(){
alert( 'done!' );
};
</pre>

start();

But what if you decide you need to execute third_async_action before second_async_action? either way, it's messy.

A good, flexibile, solution would be to do this kind of thing:

<pre>
function next(){
var action = actions[ idx++ ];
action && action();
};

var idx = 0,
actions = [
function(){
first_async_action( next );
},
function(){
second_async_action( next );
},
function(){
third_async_action( next );
},
function(){
alert( 'done!' );
}
];

next();
</pre>

Which is pretty much what jQuery's queuing methods do, internally.


Mar 2, 2010 at 9:47 AM // reply »
19 Comments

Man, I wish there was comment code syntax highlighting.


Mar 2, 2010 at 9:52 AM // reply »
11,238 Comments

@Cowboy,

Yeah, sorry about this code formatting in the comments. Never really got that nailed down quite nicely (read: at all). I'll try to make some time for that.

I see what you're saying about the sequential AJAX calls. Typically, in my apps, when I need to make sequential AJAX calls, the calls are highly coupled; meaning, the execution of the second relies heavily on the successful execution of the first. I think it would be much less likely that I would simply need to fire things sequentially.

Although, I suppose I could always clear the queue if one of the calls came back in a particular way. But even then, I wonder if my code would lose some readability?


Mar 2, 2010 at 10:09 AM // reply »
19 Comments

@Ben, I like SyntaxHighlighter personally.. you can see it in my site's comments, plugin code examples, etc. Easy to use and flexible.

http://alexgorbatchev.com/wiki/SyntaxHighlighter

Regarding the queueing stuff, I actually wrote a plugin to manage queues, but it works a bit differently than jQuery's built in queue methods. You don't use it specifically on jQuery objects, for example.

http://benalman.com/projects/jquery-message-queuing-plugin/

Still, it really makes a lot of sense to use a managed queue internally for all these animation methods, because it eliminates the whole "ridiculous nested callback" scenario.. and of course, because the queue manager is iterating over an array of queued items, it's trivial to skip a queue item or stop the queue at any time.


Mar 2, 2010 at 10:14 AM // reply »
19 Comments

BTW, here's my code as a gist for easier viewing:
http://gist.github.com/319568


Mar 2, 2010 at 10:28 AM // reply »
7 Comments

@Ben and @Cowboy, thanks for sharing this info. I'm fairly new to jQuery. Thus far I have only really used it for dynamic drop down population, but I would like to branch out into using more of it.


Mar 2, 2010 at 7:59 PM // reply »
11,238 Comments

@Cowboy,

I like the syntax highligher; unfortunately, my WYSIWYG editor (XStandard) does not allow for PRE tags. I am not sure of Script tags though, I should check into that.

Maybe I'll take a look at the way it works and see if I can port it over to the ColdFusion side. Right now, I do my formatting on Database-insert so it's only done once.

@James,

jQuery is wicked awesome! Once you start learning it, you'll be hooked!


Jun 17, 2010 at 6:14 PM // reply »
2 Comments

@Cowboy,
Could you please explain the code you written?
I was trying to follow your example, but failed (( Here is my code. Probably you could tell me where I got something wrong
Thanks!

$('.child').bind('click', function(){
var $anchor = $(this);
function next(){
var action = actions[ idx++ ];
action && action();
};

var idx = 0,
actions = [
function(){
$(function (next) {$anchor.hide('fast');});
},
function(){
$(function (next) {$anchor.show('fast');});
},
function(){
$(function (next) {$anchor.hide('fast');});
},
function(){
alert( 'done!' );
}
];

next();

});


Jun 17, 2010 at 6:46 PM // reply »
19 Comments

@tylik, it might be more helpful if you fork my gist on GitHub and ask your question there, so that we get the benefit of syntax highlighting, indenting, comments and revisions.

http://gist.github.com/319568


Jul 18, 2010 at 2:00 PM // reply »
4 Comments

Brilliant example! Though its a very simple example, I used the concept for a complicated Ajax system which had multiple steps that should be executed serially reporting the status of each step to the DOM. Amazing and a big thanks to you and your great highlights.


Jul 20, 2010 at 9:51 PM // reply »
11,238 Comments

@Mahesh,

Sounds like you found a really cool use of queue() and dequeue(). Glad that I might have provided some value in that.


Feb 12, 2012 at 9:29 AM // reply »
1 Comments

Great information


Feb 13, 2012 at 9:08 PM // reply »
4 Comments

Hello Ben,

This is just awesome, clear and easy to follow.

It helped me in a project I am doing,

Your site has become an authority on Ajax coding,

2 Thumbs up from me :)

Many Thanks,
Nader.


Feb 22, 2012 at 1:38 PM // reply »
1 Comments

Excellent explanation, thanks for the post. I have only one question, how do i get to the last effect in queue without execute others effect.


Apr 12, 2012 at 6:34 AM // reply »
1 Comments

Hi,

I have read lots of your tutorials, but i have never thanks you.
once more your explanation is very helpful and even for non english speaker it's very easy to understand.

I hope you will continue like this !


Sep 21, 2012 at 5:44 AM // reply »
1 Comments

This is what i wanted about jquery queue, explained in a super simple manner. Thanks for sharing..


Feb 19, 2013 at 8:49 AM // reply »
1 Comments

I just want to say that this post saved me!! I'm developing a blackjack game. I wanted the cards and scores to animate in the right order based on certain conditions (blackjack, bust, etc.).

To do this I was maintaining a complex and unreadable labrynth of callback functions.

Thanks to this simple little example, I fully understand how to manipulate the queue for separate elements and actions anywhere in my code.


Feb 21, 2013 at 8:55 AM // reply »
11,238 Comments

@Adrien,

Awesome! I love it when code makes thing more simple, not more complex. Heck yeah!


Mar 27, 2013 at 9:59 AM // reply »
1 Comments

I needed to queue some code recursively until a condition changed that was managed outside. Work wanted me to use the queue method rather than setInterval (no, I really don't know or care why). Had trouble, but got it figured out. Here is what worked for me (simple example) in case anyone else could use it.

  •  
  • counter = 0;
  • queueStarted = false;
  • $logo = $(".logo")
  • $logo.on("click", function(){
  • test()
  • if (!queueStarted ){
  • queueStarted = true;
  • $logo.dequeue("ma-carousel-scroll")
  • }
  • })
  • test = function () {
  • $logo
  • .queue("ma-carousel-scroll", function(next){
  • $logo.html(counter++);
  • next();
  • $logo.trigger("click");
  • })
  • .delay(1500, "ma-carousel-scroll");
  • }

Feel free to tell me if you see a more efficient way to achieve what I'm doing too.



Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 21, 2013 at 7:46 PM
Using Plupload For Drag & Drop File Uploads In ColdFusion
No luck. At least I have uncovered the cause, URLScan 3.1. Here is what I see in the IIS log when a file is over 30mb. 2013-05-21 23:29:05 10.105.45.128 GET /plupload/assets/jquery/jquery-1.8. ... read »
May 21, 2013 at 6:12 PM
Using Plupload For Drag & Drop File Uploads In ColdFusion
Ben, I did not see you after Pete Freitag's Lockdown session at cfObjective but he said that IIS sets file size limits at 30MB by default which just happened to be the threshold for file size when ... read »
May 21, 2013 at 11:51 AM
Ask Ben: Parsing Very Large XML Documents In ColdFusion
Looking at my first ever XML document that I have to parse and put into MS SQL 2000 with CF8. I get it to list the desired Field name, many times over, and have a long list of this field name displa ... read »
May 21, 2013 at 9:25 AM
Turning Off and On Identity Column in SQL Server
you are awesome..i am lucky to get this blog between such a garbage one....Thanks, Prashant ... read »
May 20, 2013 at 4:38 PM
Using A Dynamic Column Name With ValueList() In ColdFusion
@Dana, Your confusion is well founded, since this is a very confusing features. In fact, it ONLY works if you use array notation. Meaning, that this: arrayToList( query[ "columnName" ] ) ... read »
May 20, 2013 at 4:34 PM
Using A Dynamic Column Name With ValueList() In ColdFusion
I was thinking chicken and the egg, I wouldn't have expected it to work in the valuelist going in I guess. Maybe I just need a beer, long day :) ... read »
May 20, 2013 at 4:29 PM
Using A Dynamic Column Name With ValueList() In ColdFusion
@Dana, That's if you're trying to reference a specific row. In this case, we're trying to reference the entire query column as one cohesive value. So, you are correct that if you wanted to output a ... read »
May 20, 2013 at 4:24 PM
Using A Dynamic Column Name With ValueList() In ColdFusion
I thought when you used array notation to reference queries you always had to have the row or it would throw a similar error as well? ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools