5
<title>AsyncQueue</title>
6
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Maven+Pro:400,700">
7
<link rel="stylesheet" href="../../build/cssgrids/grids-min.css">
8
<link rel="stylesheet" href="../assets/css/main.css">
9
<link rel="stylesheet" href="../assets/vendor/prettify/prettify-min.css">
10
<script src="../../build/yui/yui-min.js"></script>
18
<a href="#toc" class="jump">Jump to Table of Contents</a>
22
<div class="yui3-u-3-4">
24
<div class="content"><div class="intro" class="component">
26
AsyncQueue allows you create a chain of function callbacks executed via
27
<code>setTimeout</code> that are guaranteed to run in order. This can
28
enable progressive incremental rendering of your UI so your users can
29
begin to see and interact with your page while the infrastructure is
30
being built. Similarly, process-intensive operations that will lock up
31
the UI while the JavaScript is being executed can be broken up into
32
chunks, helping to keep your interface responsive.
36
<h2 id="getting-started">Getting Started</h2>
39
To include the source files for AsyncQueue and its dependencies, first load
40
the YUI seed file if you haven't already loaded it.
43
<pre class="code prettyprint"><script src="http://yui.yahooapis.com/3.5.0/build/yui/yui-min.js"></script></pre>
47
Next, create a new YUI instance for your application and populate it with the
48
modules you need by specifying them as arguments to the <code>YUI().use()</code> method.
49
YUI will automatically load any dependencies required by the modules you
53
<pre class="code prettyprint"><script>
54
// Create a new YUI instance and populate it with the required modules.
55
YUI().use('async-queue', function (Y) {
56
// AsyncQueue is available and ready for use. Add implementation
57
// code here.
59
</script></pre>
63
For more information on creating YUI instances and on the
64
<a href="http://yuilibrary.com/yui/docs/api/classes/YUI.html#method_use"><code>use()</code> method</a>, see the
65
documentation for the <a href="../yui/index.html">YUI Global Object</a>.
69
<h2 id="using">Using AsyncQueue</h2>
71
<h3 id="interacting">Creating and interacting with an AsyncQueue</h3>
74
AsyncQueues manage an array of callbacks that can be either simple function
75
references or <a href="#callbacks">objects with specific keys</a>. The
76
primary methods on AsyncQueue are <code>add</code> and
81
When <code>run()</code> is invoked, each callback is executed in turn,
82
either synchronously or via <code>setTimeout</code> (depending on the
83
configuration of the callback or of the AsyncQueue instance).
87
Queued callbacks can also be promoted to the top of the queue or removed
91
<pre class="code prettyprint">var q = new Y.AsyncQueue(callbackB, someTask, callbackA, callbackC);
92
q.add(callbackD, callbackE); // B, someTask, A, C, D, E
93
q.promote(callbackA); // A, B, someTask, C, D, E
94
q.remove(someTask); // A, B, C, D, E
95
q.run(); // execute A, then B, then C, then D, then E</pre>
99
<h4 id="stopping">Pausing and stopping an AsyncQueue</h4>
102
In addition to <code>run()</code>, AsyncQueue instances also have
103
<code>pause()</code> and <code>stop()</code> methods to interrupt the run
108
To wait for an external process to complete, such as an XHR request, call
109
<code>pause()</code>, then <code>run()</code> again to resume
114
Call <code>stop()</code> to terminate execution and flush the AsyncQueue.
117
<pre class="code prettyprint">// Seed the instance with callbacks
118
var q = new Y.AsyncQueue(
121
// The second callback will pause the Queue and send an XHR for data
125
// Send the asynchronous XHR
126
Y.io(MyApp.getDataUri(), { on: {
127
success : function (xid,o) {
129
var data = Y.JSON.parse(o.responseText);
132
MyApp.showErrorStatus();
136
MyApp.processData(data);
138
// In the XHR callback, restart the AsyncQueue if successful
141
failure : function () {
142
MyApp.showErrorStatus();
143
// Stop the AsyncQueue if anything goes wrong
149
// The third callback will do partial updates until complete
151
fn: Y.bind(MyApp.updateUI,MyApp),
153
return MyApp.remainingData >= 0;
156
MyApp.doSomethingElse);
162
<h4 id="callbacks">About AsyncQueue callbacks</h4>
165
AsyncQueue callbacks can be simple function references or object literals
166
with the following keys:
179
<td><code>fn</code></td>
180
<td><strong>Required</strong>. The callback function to execute.</td>
184
<td><code>context</code></td>
185
<td>The context from which to execute the callback function.</td>
186
<td>The AsyncQueue instance</td>
189
<td><code>args</code></td>
190
<td>Array of arguments that will be passed as individual args to the callback function.</td>
194
<td><code>timeout</code></td>
195
<td>Millisecond delay before each execution of this callback. Set to -1 to trigger synchronous execution.</td>
199
<td><code>iterations</code></td>
200
<td>The number of times to execute this callback before shifting it from the queue.</td>
204
<td><code>until</code></td>
205
<td>A function that will return <code>true</code> when the current callback can be shifted from the queue.</td>
206
<td>a function that tests against <code>iterations</code></td>
209
<td><code>id</code></td>
210
<td>Name given to this callback for ease of reference.</td>
214
<td><code>autoContinue</code></td>
215
<td>Set to <code>false</code> to automatically <code>pause()</code> after this callback.</td>
221
<h4 id="defaults">Class- and instance-level callback defaults</h4>
224
AsyncQueue provides three places to configure callbacks (in decreasing
229
<li>The callback object</li>
230
<li>The AsyncQueue instance's <code>defaults</code> collection</li>
231
<li>The class static <code>defaults</code> collection</li>
234
<pre class="code prettyprint">// All AsyncQueue instances will execute all callbacks synchronously by default
235
Y.AsyncQueue.defaults.timeout = -1;
237
var q = new Y.AsyncQueue();
239
// run every callback in this instance twice before moving to the next callback
240
q.defaults.iterations = 2;
245
timeout: 100 // this callback will be executed asynchronously
248
// functionA executes twice immediately, then after 100 milliseconds functionB
249
// is executed, then after another 100ms functionB is executed again.
254
<h4 id="sync">Synchronous mode for callback execution</h4>
256
One of the main goals of the AsyncQueue is to provide a mechanism to
257
prevent process-intensive operations from locking up the UI. By default,
258
AsyncQueue callbacks are executed via <code>setTimeout</code> to facilitate
259
this. The <code>timeout</code> configuration accepts -1 as a value to
260
trigger synchronous callback execution. Use this setting with caution.
263
<h4 id="chaining">About timeout chaining</h4>
266
Timeout chaining is a strategy to address the lack of <a
267
href="http://en.wikipedia.org/wiki/Thread_(computer_science)">multithreading</a>
268
in JavaScript. When complex or iterative code executes it can cause the
269
page to stop responding until the running JavaScript process completes; it
270
can also cause "non-responsive script" or "long-running script" dialogs to
271
be presented to the user. Both outcomes are detrimental to user
276
To address this, the operation can be split into chunks, and
277
<code>setTimeout</code> can be used to yield control back to other
278
operations between each chunk. A common use case for this technique is to
279
allow browser reflows to display DOM modifications incrementally while
280
batches of work are being done in JavaScript. For iterative functions, the
281
code can execute a portion of the overall work, then schedule itself to run
282
via <code>setTimeout</code>.
285
<p>The basic form of an iterative timeout chain is:</p>
287
<pre class="code prettyprint">(function () {
289
/* do a chunk of the work */
291
if (/* process completion check fails */) {
292
// Schedule myself for re-execution, picking up where I left off
293
setTimeout(arguments.callee,0);
300
When dealing with <code>setTimeout</code>, it's easy to introduce race
301
conditions. Because all timeouts are scheduled against the same timer and
302
only one can run at a time, when two timeouts are separately scheduled, it
303
is possible for them to execute out of intended order.
307
AsyncQueue supports both "chunked operations" (by specifying callback
308
timeouts) and "iterative operations" (by specifying callback
309
<code>iterations</code> or <code>until</code> functions). Furthermore,
310
AsyncQueue manages the callback sequence and can therefore guarantee the
311
execution order, so you avoid race conditions.
314
<h4 id="events">Exposed events</h4>
316
AsyncQueue is based on EventTarget and instances emit the following events
317
throughout their lifecycle:
325
<th>Event payload</th>
330
<td><code>add</code></td>
331
<td>Callbacks are added to the AsyncQueue.</td>
332
<td><code>{ callbacks: (Array of callbacks added) }</code></td>
335
<td><code>promote</code></td>
336
<td>A callback is promoted.</td>
337
<td><code>{ callback : (callback) }</code></td>
340
<td><code>remove</code></td>
341
<td>A callback is removed.</td>
342
<td><code>{ callback : (callback) }</code></td>
345
<td><code>execute</code></td>
346
<td>A callback is executed.</td>
347
<td><code>{ callback : (callback) }</code></td>
350
<td><code>shift</code></td>
351
<td>A callback is shifted from the AsyncQueue.</td>
352
<td><code>{ callback : (callback) }</code></td>
355
<td><code>complete</code></td>
356
<td>After the last callback is finished executing. <em>NOT</em> fired after <code>stop()</code>.</td>
365
<div class="yui3-u-1-4">
366
<div class="sidebar">
368
<div id="toc" class="sidebox">
370
<h2 class="no-toc">Table of Contents</h2>
376
<a href="#getting-started">Getting Started</a>
379
<a href="#using">Using AsyncQueue</a>
382
<a href="#interacting">Creating and interacting with an AsyncQueue</a>
385
<a href="#stopping">Pausing and stopping an AsyncQueue</a>
388
<a href="#callbacks">About AsyncQueue callbacks</a>
391
<a href="#defaults">Class- and instance-level callback defaults</a>
394
<a href="#sync">Synchronous mode for callback execution</a>
397
<a href="#chaining">About timeout chaining</a>
400
<a href="#events">Exposed events</a>
412
<div class="sidebox">
414
<h2 class="no-toc">Examples</h2>
418
<ul class="examples">
421
<li data-description="This example employs AsyncQueue to incrementally construct an application interface; this illustrates the approach you'd take to allow chunked rendering of the UI in a process-intensive application.">
422
<a href="queue-app.html">Building a UI with AsyncQueue</a>
437
<script src="../assets/vendor/prettify/prettify-min.js"></script>
438
<script>prettyPrint();</script>