The jQuery's deferred objects, introduced in jQuery 1.5, allow us to concatenate synchronous and asynchronous actions in a chain of actions. They can be applied to animations in order to avoid nested functions, thus increasing code readability and maintainance.
The traditional approach
In the traditional approach to animations, we use nested callback functions to create sequential animations:
$('#test').animate({ left: 500 }, 1000, function() { $(this).animate({ top: 100 }, 1000, function() { $(this).animate({ left: 0 }, 1000, function() { $(this).animate({ top: 0; }, 1000); }); }); });
As you can see, code readability is seriously compromised. We can use deferred objects instead.
Using deferred objects
Let's create an object where each method is a separate animation:
var Animator = { element: '#test', moveTo: function(offset) { offset = offset || 0; $(Animator.element).animate({ left: offset }, 1000); }, moveDown: function() { $(Animator.element).animate({ top: 100 }, 1000); }, moveUp: function() { $(Animator.element).animate({ top: 0 }, 1000); } };
Then we can use the $.when()
and then()
methods of deferred objects with the new object's methods:
$('#test').click(function() { $.when(Animator.moveTo(500), Animator.moveDown()) .then(function() { Animator.moveTo(); Animator.moveUp(); }); });
Now our code is much more readable and maintainable and the final effect is exactly what we wanted: chained animations. You can see the demo below.