$.fn.extend({ myF1: function () {
var state = this.queue("myQ").pop();
this.queue("myQ", function (next) {
setTimeout(function () {
console.log("myF1");
next();
}, 3000);
});
this.queue("myQ", function () {});
if (state === undefined) {
this.dequeue("myQ");
}
return this;
},
myF2: function () {
var state = this.queue("myQ").pop();
this.queue("myQ", function (next) {
setTimeout(function () {
console.log("myF2");
next();
}, 2000);
});
this.queue("myQ", function () {});
if (state === undefined) {
this.dequeue("myQ");
}
return this;
},
myF3: function () {
var state = this.queue("myQ").pop();
this.queue("myQ", function (next) {
setTimeout(function () {
console.log("myF3");
next();
}, 1000);
});
this.queue("myQ", function () {});
if (state === undefined) {
this.dequeue("myQ");
}
return this;
},
});
$({}).myF1().myF2().myF3();
Queues or Promises
Function queues are a simple and direct way of implementing correctly chained asynchronous functions. Promises are more sophisticated but you can do the same job using the then method in a similar way to next.
The big advantage of a Promise is that it can more easily handle errors. Any failure in the chain of functions propagates and can be picked up by a single function designed to deal with the problem.
Function queues don't have the same sophistication when it comes to errors, but in many cases they don't need to. If each function in the queue checks for its own error conditions that often all that is required to handle an error is to clear the queue so that the following functions don't execute.
If this isn't a suitable error handling strategy, you will either have to implement something different or move to using the Promise object, a topic which is covered in the forthcomingJust jQuery: Events, Async & Ajax
For the moment function queues are here to stay and, even if you don't use them for your own custom queues, you will encounter them as part of any animation functions you might use and these are described in the next chapter.
Summary
Every element can have any number of function queues associated with it.
To create a queue you can make use of the .queue or the $.queue function.
When you call dequeue the function that is at the head of the queue is executed.
The key idea is that the dequeue function can be thought of as meaning "I'm finished – get on with the next function in the queue".
The purpose of using a queue is to make sure that asynchronous functions can be executed one after another without them overlapping.
To do this you have to place dequeue instructions to indicate that the function has completely finished, including any asynchronous portion. As long as you do this the functions in the queue will run one after another.
Since jQuery 1.4 the function queue has passed the next function in the queue as the first argument to the function currently being dequeued. This makes it possible to call the next function and dequeue it without having to keep a reference to the object that the queue is hosted by.
You can use the fn.extend function to add a function to jQuery.
Manually queuing and dequeuing isn't difficult, but it is a bit messy. Using the jQuery idiom of function chaining we can hide the details and still make everything work.