Timed Invocation Chain vs. Effects Queue

jQuery has a built-in mechanism for scheduling animations and effects. This is meant with effects queue (in short: fxq). This mechanism supports a wide range of animations, delays, custom queuing and unqueuing, etc. Nevertheless there are several differences between the queue and the chain. The following table tries to give a first idea:

jQuery effects queuetimed invocation chain
underlying techniqueenqueue explicite animations and effectspostpone method invocations themselves
return value of methodssame jQuery objectproxy collecting all concatenated function calls
method supportonly functions being designed to enqueue somethingany jQuery function that returns a jQuery object
combine animations and other actionsusing nested callback functionsall in the same line
loop animationsnot possible.repeat() and .until() with custom start and end conditions
method delayvia window.setTimeout() or .delay() and .queue(), using callback functions.wait(timeout).doSomething(…)

Combining animation queues and deferred jQuery chains

As you can see in the table above the concepts are quite different. Let's say it this way: the animation queue is one way to schedule effects and the deferred jQuery chain is another way to time anything.

Actually combining both concepts enables us to create complex behaviour with very few lines of code. Follow the links in the right box to the API entries of jquery-timing synchronizing deferred chains and animation queues.

.wait(…), .join(…), and .animate(…,$) – the differences

In the simple case all three kinds of synchronization behave the same:
$('.some').animate({left:100}); $('.some').wait().jQueryStuff();
//
$('.some').animate({left:100}); $('.some').join().jQueryStuff();
//
$('.some').animate({left:100},$).jQueryStuff();

Let's find out their differences:

.wait()

The easiest way to wait for animations' end calls .wait(). Internally it uses jQuery's .promise() method. Hence it only works with jQuery 1.6 and later. For earlier versions of jQuery this method will just don't wait.

We can create a case where .promise() never resolves. So this also leads to .wait() never continuing our jQuery chain:

// assure that the effects queue never gets empty
$('#example').repeat().fadeOut('slow').fadeIn('slow').join();

// do some action after .wait() - it will never happen:
$('#example').text(".wait() didn't fire").wait().text('.wait() fired!!');
Fade in, and out, forever.

.join(type)

Another method, .join(), allows to define in detail, which effects queue to wait for or whether to use .queue()/.promise() internally. If you skip the parameter usePromise or set it to false, then the .queue(function(next){…}) mechanism is used internally to register the continuation of the jQuery chain. It works with jQuery 1.4 and later.

The never continuing case above would change when using .join(). This actually would continue after one fadeOut/fadeIn iteration. But jQuery's queue mechanism can be interrupted by .stop(). So this also applies to .join(). Let's look at another case, where .join() will never fire:

// start some animations and interrupt them after 10ms
$('#example').fadeOut('slow').wait(10).stop(true);

// do some action after .join() - it will never happen:
$('#example').text(".join() didn't fire").join().text('.join() fired!!');
Fade out only

.join(type, true)

Setting usePromise to true will enforce the internal usage of .promise().done(function(){…}) for callback registration. As there is no .promise() prior to jQuery 1.6 this won't work with earlier versions.

Compared to the previously listed methods this variant behaves like the .wait() case. But it additionally allows to specify any named animation queue to wait for.

.animate(…,$)

There is also a direct way to wait for animations. Within any animation method that supports callback methods (e.g. animate(), fadeIn(), fadeOut(), slideUp(), slideDown(), …) you can replace the callback parameter by the jQuery token, $. This automatically turns the method call into a timed method call starting a deferred jQuery chain. The invocation chain continues when the animation triggers its callback.

Again we can create a case where this way of synchronization doesn't continue. Here we use that animations which are interrupted by .stop(true) will not trigger their callback:

// interrupt all animations after 10ms
$('#example').wait(10).stop(true);

// do some action after .fadeOut($) - it will never happen:
$('#example').text(".fadeOut($) waiting").fadeOut($).text('fired!!');
Fade out once.

It's up to you, the developer, to choose the best fitting synchronization method for your use case. Take a look at our example section to see these methods in action.


delays in the invocation chaindeferred jQuery chains and animationsmethod repetition with loops