+ AsyncQueue allows you create a chain of function callbacks executed via
+ setTimeout that are guaranteed to run in order. This can
+ enable progressive incremental rendering of your UI so your users can
+ begin to see and interact with your page while the infrastructure is
+ being built. Similarly, process-intensive operations that will lock up
+ the UI while the JavaScript is being executed can be broken up into
+ chunks, helping to keep your interface responsive.
+
Getting Started
+ ++To include the source files for AsyncQueue and its dependencies, first load +the YUI seed file if you haven't already loaded it. +
+ +<script src="http://yui.yahooapis.com/3.10.3/build/yui/yui-min.js"></script>+ + +
+Next, create a new YUI instance for your application and populate it with the
+modules you need by specifying them as arguments to the YUI().use() method.
+YUI will automatically load any dependencies required by the modules you
+specify.
+
<script>
+// Create a new YUI instance and populate it with the required modules.
+YUI().use('async-queue', function (Y) {
+ // AsyncQueue is available and ready for use. Add implementation
+ // code here.
+});
+</script>
+
+
+
+For more information on creating YUI instances and on the
+use() method, see the
+documentation for the YUI Global Object.
+
Using AsyncQueue
+ +Creating and interacting with an AsyncQueue
+ +
+ AsyncQueues manage an array of callbacks that can be either simple function
+ references or objects with specific keys. The
+ primary methods on AsyncQueue are add and
+ run.
+
+ When run() is invoked, each callback is executed in turn,
+ either synchronously or via setTimeout (depending on the
+ configuration of the callback or of the AsyncQueue instance).
+
+ Queued callbacks can also be promoted to the top of the queue or removed + from it. +
+ +var q = new Y.AsyncQueue(callbackB, someTask, callbackA, callbackC); +q.add(callbackD, callbackE); // B, someTask, A, C, D, E +q.promote(callbackA); // A, B, someTask, C, D, E +q.remove(someTask); // A, B, C, D, E +q.run(); // execute A, then B, then C, then D, then E+ + + +
Pausing and stopping an AsyncQueue
+ +
+ In addition to run(), AsyncQueue instances also have
+ pause() and stop() methods to interrupt the run
+ state.
+
+ To wait for an external process to complete, such as an XHR request, call
+ pause(), then run() again to resume
+ execution.
+
+ Call stop() to terminate execution and flush the AsyncQueue.
+
// Seed the instance with callbacks
+var q = new Y.AsyncQueue(
+ MyApp.doSomething,
+
+ // The second callback will pause the Queue and send an XHR for data
+ function () {
+ q.pause();
+
+ // Send the asynchronous XHR
+ Y.io(MyApp.getDataUri(), { on: {
+ success : function (xid,o) {
+ try {
+ var data = Y.JSON.parse(o.responseText);
+ }
+ catch (e) {
+ MyApp.showErrorStatus();
+ q.stop();
+ }
+
+ MyApp.processData(data);
+
+ // In the XHR callback, restart the AsyncQueue if successful
+ q.run();
+ },
+ failure : function () {
+ MyApp.showErrorStatus();
+ // Stop the AsyncQueue if anything goes wrong
+ q.stop();
+ }
+ }});
+ },
+
+ // The third callback will do partial updates until complete
+ {
+ fn: Y.bind(MyApp.updateUI,MyApp),
+ until: function () {
+ return MyApp.remainingData >= 0;
+ }
+ },
+ MyApp.doSomethingElse);
+
+q.run();
+
+
+
+About AsyncQueue callbacks
+ ++ AsyncQueue callbacks can be simple function references or object literals + with the following keys: +
+ +| property | +description | +default | +
|---|---|---|
fn |
+ Required. The callback function to execute. | +(none) | +
context |
+ The context from which to execute the callback function. | +The AsyncQueue instance | +
args |
+ Array of arguments that will be passed as individual args to the callback function. | +(none) | +
timeout |
+ Millisecond delay before each execution of this callback. Set to -1 to trigger synchronous execution. | +10 | +
iterations |
+ The number of times to execute this callback before shifting it from the queue. | +1 | +
until |
+ A function that will return true when the current callback can be shifted from the queue. |
+ a function that tests against iterations |
+
id |
+ Name given to this callback for ease of reference. | +(none) | +
autoContinue |
+ Set to false to automatically pause() after this callback. |
+ true | +
Class- and instance-level callback defaults
+ ++ AsyncQueue provides three places to configure callbacks (in decreasing + precedence order): +
+ +-
+
- The callback object +
- The AsyncQueue instance's
defaultscollection
+ - The class static
defaultscollection
+
// All AsyncQueue instances will execute all callbacks synchronously by default
+Y.AsyncQueue.defaults.timeout = -1;
+
+var q = new Y.AsyncQueue();
+
+// run every callback in this instance twice before moving to the next callback
+q.defaults.iterations = 2;
+
+q.add(functionA,
+ {
+ fn: functionB,
+ timeout: 100 // this callback will be executed asynchronously
+ });
+
+// functionA executes twice immediately, then after 100 milliseconds functionB
+// is executed, then after another 100ms functionB is executed again.
+q.run();
+
+
+
+Synchronous mode for callback execution
+
+ One of the main goals of the AsyncQueue is to provide a mechanism to
+ prevent process-intensive operations from locking up the UI. By default,
+ AsyncQueue callbacks are executed via setTimeout to facilitate
+ this. The timeout configuration accepts -1 as a value to
+ trigger synchronous callback execution. Use this setting with caution.
+
About timeout chaining
+ ++ Timeout chaining is a strategy to address the lack of multithreading + in JavaScript. When complex or iterative code executes it can cause the + page to stop responding until the running JavaScript process completes; it + can also cause "non-responsive script" or "long-running script" dialogs to + be presented to the user. Both outcomes are detrimental to user + experience. +
+ +
+ To address this, the operation can be split into chunks, and
+ setTimeout can be used to yield control back to other
+ operations between each chunk. A common use case for this technique is to
+ allow browser reflows to display DOM modifications incrementally while
+ batches of work are being done in JavaScript. For iterative functions, the
+ code can execute a portion of the overall work, then schedule itself to run
+ via setTimeout.
+
The basic form of an iterative timeout chain is:
+ +(function () {
+
+ /* do a chunk of the work */
+
+ if (/* process completion check fails */) {
+ // Schedule myself for re-execution, picking up where I left off
+ setTimeout(arguments.callee,0);
+ }
+})();
+
+
+
+
+ When dealing with setTimeout, it's easy to introduce race
+ conditions. Because all timeouts are scheduled against the same timer and
+ only one can run at a time, when two timeouts are separately scheduled, it
+ is possible for them to execute out of intended order.
+
+ AsyncQueue supports both "chunked operations" (by specifying callback
+ timeouts) and "iterative operations" (by specifying callback
+ iterations or until functions). Furthermore,
+ AsyncQueue manages the callback sequence and can therefore guarantee the
+ execution order, so you avoid race conditions.
+
Exposed events
++ AsyncQueue is based on EventTarget and instances emit the following events + throughout their lifecycle: +
+ +| Event | +When | +Event payload | +
|---|---|---|
add |
+ Callbacks are added to the AsyncQueue. | +{ callbacks: (Array of callbacks added) } |
+
promote |
+ A callback is promoted. | +{ callback : (callback) } |
+
remove |
+ A callback is removed. | +{ callback : (callback) } |
+
execute |
+ A callback is executed. | +{ callback : (callback) } |
+
shift |
+ A callback is shifted from the AsyncQueue. | +{ callback : (callback) } |
+
complete |
+ After the last callback is finished executing. NOT fired after stop(). |
+ (none) | +
