The Gallery is deprecated. No new Gallery components may be submitted, and modifying existing components is disabled. For more information please read the Gallery Deprecation blog post. This is a static snapshot of the Gallery for archive purposes.
See 42 more by this user. Created: 03/11/11
Last CDN Push: 04/13/11
Build Tag: gallery-2011.04.13-22-38
Project: YUI 3
License: YUI BSD
YUI Version: 3.5.0pr2
Free for use.
This module has been replaced by gallery-async and gallery-async-command.
"Synchronous programming is disrespectful and should not be employed in applications which are used by people." - Douglas Crockford
Asynchronous events are a wonderful tool, especially for web application development. Unfortunately, they can create a couple difficult situations and many developers attempt to avoid them by using synchronous XHR or busy waiting or something worse. Asynchronous Command Queue aims to provide a clean(ish) solution for these situations, reducing spaghetti code and putting the developer in control of when things happen.
Any asynchronous event and callback function can be wrapped in an Asynchronous Command object. It could be an io request, YQL, JSONP, or a callback from an animation or DOM event, a user input dialog or form submit, events from web workers, or anything else.
Asynchronous Command Queue will primarily help in these two situations:
There are multiple asynchronous events that need to occur in a specific order; one cannot begin until the previous one is completed. Asynchronous Command Queue helps in this situation by defining the queue as a single array of commands. This avoids the need to nest many levels of closures and callback functions. The command function code can be read from top to bottom in order.
There are multiple asynchronous events that need to occur, order is unimportant, and the application needs to be informed when all of them have completed. Asynchronous Command Queue helps in this situation by executing all of the commands right away. Especially with multiple io requests, this increases front-end performance by taking advantage of parallel processing on the remote servers, instead of waiting for one response before requesting another. The application can subscribe to the complete event to be sure that all commands have finished.
Entire Asynchronous Command Queues can be nested to provide very fine control over the timing of complex event sequences.
There is only one drawback to using Asynchronous Command Queues. Every Asynchronous Command MUST be manually completed. It's easy to do: asynchronousCommand.fire('complete); but it's also easy to forget to do. If any Asynchronous Command does not complete, the Asynchronous Command Queue will stop firing events and anything in the application waiting on those events will never run.
Recent Changes:
Pause/Resume events and methods have been removed from Y.AsynchronousCommandQueue. It should be good enough to set the paused attribute and subscribe to its change event.
Bugfix: The delay attribute on Y.AsynchronousCommand is now writeOnce: 'initOnly' instead of readOnly: true.
Bugfix: Calling the startAll method on Y.AsynchronousCommandQueue will now fire the complete event if the queue is empty.
Y.AsynchronousCommand is an instanceable object. Its constructor function accepts an attributes object with the following members.
args: an array of arguments which will be applied to the command function.
context: the execution context of the command function. Defaults to Y.config.win
delay: optional millisecond wait time between executing the command and calling the command function. Defaults to 0
fn: the command function. function (asynchronousCommand, ... (args)) {// This is where an asynchronous event and callback function are defined.} The first argument to this function is always this AsynchronousCommand object. This function MUST always complete the command: asynchronousCommand.fire('complete'); Do this in the callback of the asynchronous event.
Each Y.AsynchronousCommand instance has two public events.
complete: fireOnce: fired by the command function when the asynchronous event is complete.
start: fireOnce: fired when the command function is called (after delay)
Each Y.AsynchronousCommand instance has one public method.
execute: waits for delay, then calls the command function. This method is chainable.
Each Y.AsynchronousCommand instance has two readOnly attributes.
completed: boolean. Will become true on the complete event.
started: boolean. Will become true on the start event.
Y.AsynchronousCommandQueue is an instanceable object. Its constructor function accepts an attributes object with the following member.
queue: an array of Y.AsynchronousCommand instances.
Each Y.AsynchronousCommandQueue instance has two public events.
complete: fireOnce: fired when all commands have completed.
start: fireOnce: fired when the first command is executed.
Each Y.AsynchronousCommandQueue instance has four public methods.
addCommand: accepts one Y.AsynchronousCommand instance and pushes it on the queue. This method is chainable. Adding commands to the queue after the queue has been started 'should' work as long as the queue has not completed. For more control over the order in which commands are inserted into the queue, create an array of commands, perform the necessary inserts into the array, and use that array as the queue attribute in the constructor function.
getCommandCount: returns the length of the queue.
startAll: executes every command in the queue immediately. This method is chainable.
startQueue: shifts the first command off the queue and executes it. This method is chainable. As long as there are still commands in the queue, startQueue will be called again when the command completes. If the queue is paused, startQueue does nothing.
Each Y.AsynchronousCommandQueue instance has three other attributes.
completed: readOnly: boolean. Will become true on the complete event.
paused: boolean
started: readOnly: boolean. Will become true on the start event.
<script src="http://yui.yahooapis.com/3.5.0pr2/build/yui/yui-min.js"></script>
YUI({
//Last Gallery Build of this module
gallery: 'gallery-2011.04.13-22-38'
}).use('gallery-asynchronouscommandqueue', function(Y) {
// Example 1: startQueue();
// Each command depends on the previous command so they are executed
// one-by-one in order.
// For this example, each command is a simple Y.later with a random wait time.
(function () {
var result = [];
new Y.AsynchronousCommandQueue({
queue: [
new Y.AsynchronousCommand({
fn: function (asynchronousCommand) {
Y.later(Math.floor(Math.random() * 1000), null, function () {
result.push(1);
asynchronousCommand.fire('complete');
});
}
}),
new Y.AsynchronousCommand({
fn: function (asynchronousCommand) {
Y.later(Math.floor(Math.random() * 1000), null, function () {
result.push(result[0] + 2);
asynchronousCommand.fire('complete');
});
}
}),
new Y.AsynchronousCommand({
fn: function (asynchronousCommand) {
Y.later(Math.floor(Math.random() * 1000), null, function () {
result.push(result[1] + 3);
asynchronousCommand.fire('complete');
});
}
}),
new Y.AsynchronousCommand({
fn: function (asynchronousCommand) {
Y.later(Math.floor(Math.random() * 1000), null, function () {
result.push(result[2] + 4);
asynchronousCommand.fire('complete');
});
}
}),
new Y.AsynchronousCommand({
fn: function (asynchronousCommand) {
Y.later(Math.floor(Math.random() * 1000), null, function () {
result.push(result[3] + 5);
asynchronousCommand.fire('complete');
});
}
}),
]
}).startQueue().on('complete', function () {
alert(result[4]);
});
}());
// Example 2: startAll();
// Each command is independent and does not rely upon other commands.
// The commands are all executed immediately.
// Once all commands have completed, the application continues and has valid
// data provided by all commands.
// For this example, each command is a simple Y.later with a random wait time.
(function () {
var a, b, c, d, e;
new Y.AsynchronousCommandQueue({
queue: [
new Y.AsynchronousCommand({
fn: function (asynchronousCommand) {
Y.later(Math.floor(Math.random() * 5000), null, function () {
a = 1;
asynchronousCommand.fire('complete');
});
}
}),
new Y.AsynchronousCommand({
fn: function (asynchronousCommand) {
Y.later(Math.floor(Math.random() * 5000), null, function () {
b = 2;
asynchronousCommand.fire('complete');
});
}
}),
new Y.AsynchronousCommand({
fn: function (asynchronousCommand) {
Y.later(Math.floor(Math.random() * 5000), null, function () {
c = 3;
asynchronousCommand.fire('complete');
});
}
}),
new Y.AsynchronousCommand({
fn: function (asynchronousCommand) {
Y.later(Math.floor(Math.random() * 5000), null, function () {
d = 4;
asynchronousCommand.fire('complete');
});
}
}),
new Y.AsynchronousCommand({
fn: function (asynchronousCommand) {
Y.later(Math.floor(Math.random() * 5000), null, function () {
e = 5;
asynchronousCommand.fire('complete');
});
}
}),
]
}).startAll().on('complete', function () {
alert(a + b + c + d + e);
});
}());
});
Subject | Author | Date |
---|---|---|
Good ideas here | Luke Smith | 03/15/11 |
Re: Good ideas here | Steven Olmsted | 03/17/11 |
All code on this site is licensed under the BSD License unless stated otherwise.