Sever PlotKit's weak dependency on MochiKit.Format -> 126k
[dygraphs.git] / mochikit_v14 / doc / rst / MochiKit / Async.rst
CommitLineData
6a1aa64f
DV
1.. title:: MochiKit.Async - manage asynchronous tasks
2
3Name
4====
5
6MochiKit.Async - manage asynchronous tasks
7
8
9Synopsis
10========
11
12::
13
14 var url = "/src/b/bo/bob/MochiKit.Async/META.json";
15 /*
16
17 META.json looks something like this:
18
19 {"name": "MochiKit", "version": "0.5"}
20
21 */
22 var d = loadJSONDoc(url);
23 var gotMetadata = function (meta) {
24 if (MochiKit.Async.VERSION == meta.version) {
25 alert("You have the newest MochiKit.Async!");
26 } else {
27 alert("MochiKit.Async "
28 + meta.version
29 + " is available, upgrade!");
30 }
31 };
32 var metadataFetchFailed = function (err) {
33 alert("The metadata for MochiKit.Async could not be fetched :(");
34 };
35 d.addCallbacks(gotMetadata, metadataFetchFailed);
36
37
38Description
39===========
40
41MochiKit.Async provides facilities to manage asynchronous (as in AJAX
42[1]_) tasks. The model for asynchronous computation used in this
43module is heavily inspired by Twisted [2]_.
44
45
46Dependencies
47============
48
49- :mochiref:`MochiKit.Base`
50
51
52Overview
53========
54
55Deferred
56--------
57
58The Deferred constructor encapsulates a single value that is not
59available yet. The most important example of this in the context of a
60web browser would be an ``XMLHttpRequest`` to a server. The importance
61of the Deferred is that it allows a consistent API to be exposed for
62all asynchronous computations that occur exactly once.
63
64The producer of the Deferred is responsible for doing all of the
65complicated work behind the scenes. This often means waiting for a
66timer to fire, or waiting for an event (e.g. ``onreadystatechange`` of
67``XMLHttpRequest``). It could also be coordinating several events
68(e.g. ``XMLHttpRequest`` with a timeout, or several Deferreds
69(e.g. fetching a set of XML documents that should be processed at the
70same time).
71
72Since these sorts of tasks do not respond immediately, the producer of
73the Deferred does the following steps before returning to the
74consumer:
75
761. Create a ``new`` :mochiref:`Deferred();` object and keep a
77 reference to it, because it will be needed later when the value is
78 ready.
792. Setup the conditions to create the value requested (e.g. create a
80 new ``XMLHttpRequest``, set its ``onreadystatechange``).
813. Return the :mochiref:`Deferred` object.
82
83Since the value is not yet ready, the consumer attaches a function to
84the Deferred that will be called when the value is ready. This is not
85unlike ``setTimeout``, or other similar facilities you may already be
86familiar with. The consumer can also attach an "errback" to the
87:mochiref:`Deferred`, which is a callback for error handling.
88
89When the value is ready, the producer simply calls
90``myDeferred.callback(theValue)``. If an error occurred, it should
91call ``myDeferred.errback(theValue)`` instead. As soon as this
92happens, the callback that the consumer attached to the
93:mochiref:`Deferred` is called with ``theValue`` as the only argument.
94
95There are quite a few additional "advanced" features baked into
96:mochiref:`Deferred`, such as cancellation and callback chains, so
97take a look at the API reference if you would like to know more!
98
99API Reference
100=============
101
102Errors
103------
104
105:mochidef:`AlreadyCalledError`:
106
107 Thrown by a :mochiref:`Deferred` if ``.callback`` or ``.errback``
108 are called more than once.
109
110 *Availability*:
111 Available in MochiKit 1.3.1+
112
113
114:mochidef:`BrowserComplianceError`:
115
116 Thrown when the JavaScript runtime is not capable of performing
117 the given function. Currently, this happens if the browser does
118 not support ``XMLHttpRequest``.
119
120 *Availability*:
121 Available in MochiKit 1.3.1+
122
123
124:mochidef:`CancelledError`:
125
126 Thrown by a :mochiref:`Deferred` when it is cancelled, unless a
127 canceller is present and throws something else.
128
129 *Availability*:
130 Available in MochiKit 1.3.1+
131
132
133:mochidef:`GenericError`:
134
135 Results passed to ``.fail`` or ``.errback`` of a
136 :mochiref:`Deferred` are wrapped by this ``Error`` if ``!(result
137 instanceof Error)``.
138
139 *Availability*:
140 Available in MochiKit 1.3.1+
141
142
143:mochidef:`XMLHttpRequestError`:
144
145 Thrown when an ``XMLHttpRequest`` does not complete successfully
146 for any reason. The ``req`` property of the error is the failed
147 ``XMLHttpRequest`` object, and for convenience the ``number``
148 property corresponds to ``req.status``.
149
150 *Availability*:
151 Available in MochiKit 1.3.1+
152
153
154Constructors
155------------
156
157:mochidef:`Deferred()`:
158
159 Encapsulates a sequence of callbacks in response to a value that
160 may not yet be available. This is modeled after the Deferred class
161 from Twisted [3]_.
162
163.. _`Twisted`: http://twistedmatrix.com/
164
165 Why do we want this? JavaScript has no threads, and even if it
166 did, threads are hard. Deferreds are a way of abstracting
167 non-blocking events, such as the final response to an
168 ``XMLHttpRequest``.
169
170 The sequence of callbacks is internally represented as a list of
171 2-tuples containing the callback/errback pair. For example, the
172 following call sequence::
173
174 var d = new Deferred();
175 d.addCallback(myCallback);
176 d.addErrback(myErrback);
177 d.addBoth(myBoth);
178 d.addCallbacks(myCallback, myErrback);
179
180 is translated into a :mochiref:`Deferred` with the following
181 internal representation::
182
183 [
184 [myCallback, null],
185 [null, myErrback],
186 [myBoth, myBoth],
187 [myCallback, myErrback]
188 ]
189
190 The :mochiref:`Deferred` also keeps track of its current status
191 (fired). Its status may be one of the following three values:
192
193
194 ===== ================================
195 Value Condition
196 ===== ================================
197 -1 no value yet (initial condition)
198 0 success
199 1 error
200 ===== ================================
201
202 A :mochiref:`Deferred` will be in the error state if one of the
203 following conditions are met:
204
205 1. The result given to callback or errback is "``instanceof
206 Error``"
207 2. The callback or errback threw while executing. If the thrown
208 object is not ``instanceof Error``, it will be wrapped with
209 :mochiref:`GenericError`.
210
211 Otherwise, the :mochiref:`Deferred` will be in the success
212 state. The state of the :mochiref:`Deferred` determines the next
213 element in the callback sequence to run.
214
215 When a callback or errback occurs with the example deferred chain,
216 something equivalent to the following will happen (imagine that
217 exceptions are caught and returned as-is)::
218
219 // d.callback(result) or d.errback(result)
220 if (!(result instanceof Error)) {
221 result = myCallback(result);
222 }
223 if (result instanceof Error) {
224 result = myErrback(result);
225 }
226 result = myBoth(result);
227 if (result instanceof Error) {
228 result = myErrback(result);
229 } else {
230 result = myCallback(result);
231 }
232
233 The result is then stored away in case another step is added to
234 the callback sequence. Since the :mochiref:`Deferred` already has
235 a value available, any new callbacks added will be called
236 immediately.
237
238 There are two other "advanced" details about this implementation
239 that are useful:
240
241 Callbacks are allowed to return :mochiref:`Deferred` instances, so
242 you can build complicated sequences of events with (relative)
243 ease.
244
245 The creator of the :mochiref:`Deferred` may specify a
246 canceller. The canceller is a function that will be called if
247 :mochiref:`Deferred.prototype.cancel` is called before the
248 :mochiref:`Deferred` fires. You can use this to allow an
249 ``XMLHttpRequest`` to be cleanly cancelled, for example. Note that
250 cancel will fire the :mochiref:`Deferred` with a
251 :mochiref:`CancelledError` (unless your canceller throws or
252 returns a different ``Error``), so errbacks should be prepared to
253 handle that ``Error`` gracefully for cancellable
254 :mochiref:`Deferred` instances.
255
256 *Availability*:
257 Available in MochiKit 1.3.1+
258
259
260:mochidef:`Deferred.prototype.addBoth(func)`:
261
262 Add the same function as both a callback and an errback as the
263 next element on the callback sequence. This is useful for code
264 that you want to guarantee to run, e.g. a finalizer.
265
266 If additional arguments are given, then ``func`` will be replaced
267 with :mochiref:`MochiKit.Base.partial.apply(null,
268 arguments)`. This differs from `Twisted`_, because the result of
269 the callback or errback will be the *last* argument passed to
270 ``func``.
271
272 If ``func`` returns a :mochiref:`Deferred`, then it will be
273 chained (its value or error will be passed to the next
274 callback). Note that once the returned ``Deferred`` is chained, it
275 can no longer accept new callbacks.
276
277 *Availability*:
278 Available in MochiKit 1.3.1+
279
280
281:mochidef:`Deferred.prototype.addCallback(func[, ...])`:
282
283 Add a single callback to the end of the callback sequence.
284
285 If additional arguments are given, then ``func`` will be replaced
286 with :mochiref:`MochiKit.Base.partial.apply(null,
287 arguments)`. This differs from `Twisted`_, because the result of
288 the callback will be the *last* argument passed to ``func``.
289
290 If ``func`` returns a :mochiref:`Deferred`, then it will be
291 chained (its value or error will be passed to the next
292 callback). Note that once the returned ``Deferred`` is chained, it
293 can no longer accept new callbacks.
294
295 *Availability*:
296 Available in MochiKit 1.3.1+
297
298
299:mochidef:`Deferred.prototype.addCallbacks(callback, errback)`:
300
301 Add separate callback and errback to the end of the callback
302 sequence. Either callback or errback may be ``null``, but not
303 both.
304
305 If ``callback`` or ``errback`` returns a :mochiref:`Deferred`,
306 then it will be chained (its value or error will be passed to the
307 next callback). Note that once the returned ``Deferred`` is
308 chained, it can no longer accept new callbacks.
309
310 *Availability*:
311 Available in MochiKit 1.3.1+
312
313
314:mochidef:`Deferred.prototype.addErrback(func)`:
315
316 Add a single errback to the end of the callback sequence.
317
318 If additional arguments are given, then ``func`` will be replaced
319 with :mochiref:`MochiKit.Base.partial.apply(null,
320 arguments)`. This differs from `Twisted`_, because the result of
321 the errback will be the *last* argument passed to ``func``.
322
323 If ``func`` returns a :mochiref:`Deferred`, then it will be
324 chained (its value or error will be passed to the next
325 callback). Note that once the returned ``Deferred`` is chained, it
326 can no longer accept new callbacks.
327
328 *Availability*:
329 Available in MochiKit 1.3.1+
330
331
332:mochidef:`Deferred.prototype.callback([result])`:
333
334 Begin the callback sequence with a non-``Error`` result. Result
335 may be any value except for a :mochiref:`Deferred`.
336
337 Either ``.callback`` or ``.errback`` should be called exactly once
338 on a :mochiref:`Deferred`.
339
340 *Availability*:
341 Available in MochiKit 1.3.1+
342
343
344:mochidef:`Deferred.prototype.cancel()`:
345
346 Cancels a :mochiref:`Deferred` that has not yet received a value,
347 or is waiting on another :mochiref:`Deferred` as its value.
348
349 If a canceller is defined, the canceller is called. If the
350 canceller did not return an ``Error``, or there was no canceller,
351 then the errback chain is started with :mochiref:`CancelledError`.
352
353 *Availability*:
354 Available in MochiKit 1.3.1+
355
356
357:mochidef:`Deferred.prototype.errback([result])`:
358
359 Begin the callback sequence with an error result. Result may be
360 any value except for a :mochiref:`Deferred`, but if ``!(result
361 instanceof Error)``, it will be wrapped with
362 :mochiref:`GenericError`.
363
364 Either ``.callback`` or ``.errback`` should be called exactly once
365 on a :mochidef:`Deferred`.
366
367 *Availability*:
368 Available in MochiKit 1.3.1+
369
370
371:mochidef:`DeferredLock()`:
372
373 A lock for asynchronous systems.
374
375 The ``locked`` property of a :mochiref:`DeferredLock` will be
376 ``true`` if it locked, ``false`` otherwise. Do not change this
377 property.
378
379 *Availability*:
380 Available in MochiKit 1.3.1+
381
382
383:mochidef:`DeferredLock.prototype.acquire()`:
384
385 Attempt to acquire the lock. Returns a :mochiref:`Deferred` that
386 fires on lock acquisition with the :mochiref:`DeferredLock` as the
387 value. If the lock is locked, then the :mochiref:`Deferred` goes
388 into a waiting list.
389
390 *Availability*:
391 Available in MochiKit 1.3.1+
392
393
394:mochidef:`DeferredLock.prototype.release()`:
395
396 Release the lock. If there is a waiting list, then the first
397 :mochiref:`Deferred` in that waiting list will be called back.
398
399 *Availability*:
400 Available in MochiKit 1.3.1+
401
402
403:mochidef:`DeferredList(list, [fireOnOneCallback, fireOnOneErrback, consumeErrors, canceller])`:
404
405 Combine a list of :mochiref:`Deferred` into one. Track the
406 callbacks and return a list of (success, result) tuples, 'success'
407 being a boolean indicating whether result is a normal result or an
408 error.
409
410 Once created, you have access to all :mochiref:`Deferred` methods,
411 like addCallback, addErrback, addBoth. The behaviour can be
412 changed by the following options:
413
414 ``fireOnOneCallback``:
415 Flag for launching the callback once the first Deferred of the
416 list has returned.
417
418 ``fireOnOneErrback``:
419 Flag for calling the errback at the first error of a Deferred.
420
421 ``consumeErrors``:
422 Flag indicating that any errors raised in the Deferreds should
423 be consumed by the DeferredList.
424
425 Example::
426
427 // We need to fetch data from 2 different urls
428 var d1 = loadJSONDoc(url1);
429 var d2 = loadJSONDoc(url2);
430 var l1 = new DeferredList([d1, d2], false, false, true);
431 l1.addCallback(function (resultList) {
432 MochiKit.Base.map(function (result) {
433 if (result[0]) {
434 alert("Data is here: " + result[1]);
435 } else {
436 alert("Got an error: " + result[1]);
437 }
438 }, resultList);
439 });
440
441 *Availability*:
442 Available in MochiKit 1.3.1+
443
444
445Functions
446---------
447
448:mochidef:`callLater(seconds, func[, args...])`:
449
450 Call ``func(args...)`` after at least ``seconds`` seconds have
451 elapsed. This is a convenience method for::
452
453 func = partial.apply(extend(null, arguments, 1));
454 return wait(seconds).addCallback(function (res) { return func() });
455
456 Returns a cancellable :mochiref:`Deferred`.
457
458 *Availability*:
459 Available in MochiKit 1.3.1+
460
461
462:mochidef:`doXHR(url[, {option: value, ...}])`:
463
464 Perform a customized ``XMLHttpRequest`` and wrap it with a
465 :mochiref:`Deferred` that may be cancelled.
466
467 Note that only ``200`` (OK), ``201`` (CREATED),
468 ``204`` (NO CONTENT) and ``304`` (NOT MODIFIED) are considered
469 success codes. All other status codes will
470 result in an errback with an ``XMLHttpRequestError``.
471
472 ``url``:
473 The URL for this request.
474
475 The following options are currently accepted:
476
477 ``method``:
478 The HTTP method. Default is ``'GET'``.
479
480 ``sendContent``:
481 The content to send (e.g. with POST). Default is no content.
482
483 ``queryString``:
484 If present it will be used to build a query string to append to
485 the url using :mochiref:`MochiKit.Base.queryString`. Default is
486 no query string.
487
488 ``username``:
489 The username for the request. Default is no username.
490
491 ``password``:
492 The password for the request. Default is no password.
493
494 ``headers``:
495 Additional headers to set in the request, either as an object
496 such as ``{'Accept': 'text/xml'}`` or as an Array of 2-Arrays
497 ``[['Accept', 'text/xml']]``. Default is no additional headers.
498
499 ``mimeType``:
500 An override mime type. The typical use of this is to pass
501 'text/xml' to force XMLHttpRequest to attempt to parse responseXML.
502 Default is no override.
503
504 *returns*:
505 :mochiref:`Deferred` that will callback with the
506 ``XMLHttpRequest`` instance on success
507
508 *Availability*:
509 Available in MochiKit 1.4+.
510
511
512:mochidef:`doSimpleXMLHttpRequest(url[, queryArguments...])`:
513
514 Perform a simple ``XMLHttpRequest`` and wrap it with a
515 :mochiref:`Deferred` that may be cancelled.
516
517 Note that only ``200`` (OK), ``201`` (CREATED),
518 ``204`` (NO CONTENT) and ``304`` (NOT MODIFIED) are considered
519 success codes. All other status codes will
520 result in an errback with an ``XMLHttpRequestError``.
521
522 ``url``:
523 The URL to GET
524
525 ``queryArguments``:
526 If this function is called with more than one argument, a
527 ``"?"`` and the result of
528 :mochiref:`MochiKit.Base.queryString` with the rest of the
529 arguments are appended to the URL.
530
531 For example, this will do a GET request to the URL
532 ``http://example.com?bar=baz``::
533
534 doSimpleXMLHttpRequest("http://example.com", {bar: "baz"});
535
536 *returns*:
537 :mochiref:`Deferred` that will callback with the
538 ``XMLHttpRequest`` instance on success
539
540 *Availability*:
541 Available in MochiKit 1.3.1+. Support for 201 and 204 were added in
542 MochiKit 1.4.
543
544
545:mochidef:`evalJSONRequest(req)`:
546
547 Evaluate a JSON [4]_ ``XMLHttpRequest``
548
549 ``req``:
550 The request whose ``.responseText`` property is to be
551 evaluated
552
553 *returns*:
554 A JavaScript object
555
556 *Availability*:
557 Available in MochiKit 1.3.1+
558
559
560:mochidef:`fail([result])`:
561
562 Return a :mochiref:`Deferred` that has already had
563 ``.errback(result)`` called.
564
565 See ``succeed`` documentation for rationale.
566
567 ``result``:
568 The result to give to
569 :mochiref:`Deferred.prototype.errback(result)`.
570
571 *returns*:
572 A ``new`` :mochiref:`Deferred()`
573
574 *Availability*:
575 Available in MochiKit 1.3.1+
576
577
578:mochidef:`gatherResults(deferreds)`:
579
580 A convenience function that returns a :mochiref:`DeferredList`
581 from the given ``Array`` of :mochiref:`Deferred` instances that
582 will callback with an ``Array`` of just results when they're
583 available, or errback on the first array.
584
585 *Availability*:
586 Available in MochiKit 1.3.1+
587
588
589:mochidef:`getXMLHttpRequest()`:
590
591 Return an ``XMLHttpRequest`` compliant object for the current
592 platform.
593
594 In order of preference:
595
596 - ``new XMLHttpRequest()``
597 - ``new ActiveXObject('Msxml2.XMLHTTP')``
598 - ``new ActiveXObject('Microsoft.XMLHTTP')``
599 - ``new ActiveXObject('Msxml2.XMLHTTP.4.0')``
600
601 *Availability*:
602 Available in MochiKit 1.3.1+
603
604
605:mochidef:`maybeDeferred(func[, argument...])`:
606
607 Call a ``func`` with the given arguments and ensure the result is
608 a :mochiref:`Deferred`.
609
610 ``func``:
611 The function to call.
612
613 *returns*:
614 A new :mochiref:`Deferred` based on the call to ``func``. If
615 ``func`` does not naturally return a :mochiref:`Deferred`, its
616 result or error value will be wrapped by one.
617
618 *Availability*:
619 Available in MochiKit 1.3.1+
620
621
622:mochidef:`loadJSONDoc(url[, queryArguments...])`:
623
624 Do a simple ``XMLHttpRequest`` to a URL and get the response as a
625 JSON [4]_ document.
626
627 ``url``:
628 The URL to GET
629
630 ``queryArguments``:
631 If this function is called with more than one argument, a
632 ``"?"`` and the result of
633 :mochiref:`MochiKit.Base.queryString` with the rest of the
634 arguments are appended to the URL.
635
636 For example, this will do a GET request to the URL
637 ``http://example.com?bar=baz``::
638
639 loadJSONDoc("http://example.com", {bar: "baz"});
640
641 *returns*:
642 :mochiref:`Deferred` that will callback with the evaluated
643 JSON [4]_ response upon successful ``XMLHttpRequest``
644
645 *Availability*:
646 Available in MochiKit 1.3.1+
647
648
649:mochidef:`sendXMLHttpRequest(req[, sendContent])`:
650
651 Set an ``onreadystatechange`` handler on an ``XMLHttpRequest``
652 object and send it off. Will return a cancellable
653 :mochiref:`Deferred` that will callback on success.
654
655 Note that only ``200`` (OK), ``201`` (CREATED),
656 ``204`` (NO CONTENT) and ``304`` (NOT MODIFIED) are considered
657 success codes. All other status codes will
658 result in an errback with an ``XMLHttpRequestError``.
659
660 ``req``:
661 An preconfigured ``XMLHttpRequest`` object (open has been
662 called).
663
664 ``sendContent``:
665 Optional string or DOM content to send over the
666 ``XMLHttpRequest``.
667
668 *returns*:
669 :mochiref:`Deferred` that will callback with the
670 ``XMLHttpRequest`` instance on success.
671
672 *Availability*:
673 Available in MochiKit 1.3.1+. Support for 201 and 204 were added in
674 MochiKit 1.4.
675
676
677:mochidef:`succeed([result])`:
678
679 Return a :mochiref:`Deferred` that has already had
680 ``.callback(result)`` called.
681
682 This is useful when you're writing synchronous code to an
683 asynchronous interface: i.e., some code is calling you expecting a
684 :mochiref:`Deferred` result, but you don't actually need to do
685 anything asynchronous. Just return ``succeed(theResult)``.
686
687 See ``fail`` for a version of this function that uses a failing
688 :mochiref:`Deferred` rather than a successful one.
689
690 ``result``:
691 The result to give to
692 :mochiref:`Deferred.prototype.callback(result)`
693
694 *returns*:
695 a ``new`` :mochiref:`Deferred`
696
697 *Availability*:
698 Available in MochiKit 1.3.1+
699
700
701:mochidef:`wait(seconds[, res])`:
702
703 Return a new cancellable :mochiref:`Deferred` that will
704 ``.callback(res)`` after at least ``seconds`` seconds have
705 elapsed.
706
707 *Availability*:
708 Available in MochiKit 1.3.1+
709
710
711See Also
712========
713
714.. [1] AJAX, Asynchronous JavaScript and XML: http://en.wikipedia.org/wiki/AJAX
715.. [2] Twisted, an event-driven networking framework written in Python: http://twistedmatrix.com/
716.. [3] Twisted Deferred Reference: http://twistedmatrix.com/projects/core/documentation/howto/defer.html
717.. [4] JSON, JavaScript Object Notation: http://json.org/
718
719
720Authors
721=======
722
723- Bob Ippolito <bob@redivi.com>
724
725
726Copyright
727=========
728
729Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is
730dual-licensed free software; you can redistribute it and/or modify it
731under the terms of the `MIT License`_ or the `Academic Free License
732v2.1`_.
733
734.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
735.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php