source: Dev/trunk/src/node_modules/q/README.md @ 484

Last change on this file since 484 was 484, checked in by hendrikvanantwerpen, 11 years ago

Commit node_modules, to make checkouts and builds more deterministic.

File size: 22.3 KB
Line 
1[![Build Status](https://secure.travis-ci.org/kriskowal/q.png?branch=master)](http://travis-ci.org/kriskowal/q)
2
3<a href="http://promises-aplus.github.com/promises-spec">
4    <img src="http://promises-aplus.github.com/promises-spec/assets/logo-small.png"
5         align="right" alt="Promises/A+ logo" />
6</a>
7
8If a function cannot return a value or throw an exception without
9blocking, it can return a promise instead.  A promise is an object
10that represents the return value or the thrown exception that the
11function may eventually provide.  A promise can also be used as a
12proxy for a [remote object][Q-Connection] to overcome latency.
13
14[Q-Connection]: https://github.com/kriskowal/q-connection
15
16On the first pass, promises can mitigate the “[Pyramid of
17Doom][POD]”: the situation where code marches to the right faster
18than it marches forward.
19
20[POD]: http://calculist.org/blog/2011/12/14/why-coroutines-wont-work-on-the-web/
21
22```javascript
23step1(function (value1) {
24    step2(value1, function(value2) {
25        step3(value2, function(value3) {
26            step4(value3, function(value4) {
27                // Do something with value4
28            });
29        });
30    });
31});
32```
33
34With a promise library, you can flatten the pyramid.
35
36```javascript
37Q.fcall(step1)
38.then(step2)
39.then(step3)
40.then(step4)
41.then(function (value4) {
42    // Do something with value4
43}, function (error) {
44    // Handle any error from step1 through step4
45})
46.done();
47```
48
49With this approach, you also get implicit error propagation,
50just like ``try``, ``catch``, and ``finally``.  An error in
51``step1`` will flow all the way to ``step5``, where it’s
52caught and handled.
53
54The callback approach is called an “inversion of control”.
55A function that accepts a callback instead of a return value
56is saying, “Don’t call me, I’ll call you.”.  Promises
57[un-invert][IOC] the inversion, cleanly separating the input
58arguments from control flow arguments.  This simplifies the
59use and creation of API’s, particularly variadic,
60rest and spread arguments.
61
62[IOC]: http://www.slideshare.net/domenicdenicola/callbacks-promises-and-coroutines-oh-my-the-evolution-of-asynchronicity-in-javascript
63
64
65## Getting Started
66
67The Q module can be loaded as:
68
69-   A ``<script>`` tag (creating a ``Q`` global variable): ~2.5 KB minified and
70    gzipped.
71-   A Node.js and CommonJS module, available in [npm](https://npmjs.org/) as
72    the [q](https://npmjs.org/package/q) package
73-   An AMD module
74-   A [component](https://github.com/component/component) as ``microjs/q``
75-   Using [bower](http://bower.io/) as ``q``
76-   Using [NuGet](http://nuget.org/) as [Q](https://nuget.org/packages/q)
77
78Q can exchange promises with jQuery, Dojo, When.js, WinJS, and more.
79Additionally, there are many libraries that produce and consume Q promises for
80everything from file system/database access or RPC to templating. For a list of
81some of the more popular ones, see [Libraries][].
82
83Please join the Q-Continuum [mailing list](https://groups.google.com/forum/#!forum/q-continuum).
84
85[Libraries]: https://github.com/kriskowal/q/wiki/Libraries
86
87
88## Tutorial
89
90Promises have a ``then`` method, which you can use to get the eventual
91return value (fulfillment) or thrown exception (rejection).
92
93```javascript
94promiseMeSomething()
95.then(function (value) {
96}, function (reason) {
97});
98```
99
100If ``promiseMeSomething`` returns a promise that gets fulfilled later
101with a return value, the first function (the fulfillment handler) will be
102called with the value.  However, if the ``promiseMeSomething`` function
103gets rejected later by a thrown exception, the second function (the
104rejection handler) will be called with the exception.
105
106Note that resolution of a promise is always asynchronous: that is, the
107fulfillment or rejection handler will always be called in the next turn of the
108event loop (i.e. `process.nextTick` in Node). This gives you a nice
109guarantee when mentally tracing the flow of your code, namely that
110``then`` will always return before either handler is executed.
111
112
113### Propagation
114
115The ``then`` method returns a promise, which in this example, I’m
116assigning to ``outputPromise``.
117
118```javascript
119var outputPromise = getInputPromise()
120.then(function (input) {
121}, function (reason) {
122});
123```
124
125The ``outputPromise`` variable becomes a new promise for the return
126value of either handler.  Since a function can only either return a
127value or throw an exception, only one handler will ever be called and it
128will be responsible for resolving ``outputPromise``.
129
130-   If you return a value in a handler, ``outputPromise`` will get
131    fulfilled.
132
133-   If you throw an exception in a handler, ``outputPromise`` will get
134    rejected.
135
136-   If you return a **promise** in a handler, ``outputPromise`` will
137    “become” that promise.  Being able to become a new promise is useful
138    for managing delays, combining results, or recovering from errors.
139
140If the ``getInputPromise()`` promise gets rejected and you omit the
141rejection handler, the **error** will go to ``outputPromise``:
142
143```javascript
144var outputPromise = getInputPromise()
145.then(function (value) {
146});
147```
148
149If the input promise gets fulfilled and you omit the fulfillment handler, the
150**value** will go to ``outputPromise``:
151
152```javascript
153var outputPromise = getInputPromise()
154.then(null, function (error) {
155});
156```
157
158Q promises provide a ``fail`` shorthand for ``then`` when you are only
159interested in handling the error:
160
161```javascript
162var outputPromise = getInputPromise()
163.fail(function (error) {
164});
165```
166
167If you are writing JavaScript for modern engines only or using
168CoffeeScript, you may use `catch` instead of `fail`.
169
170Promises also have a ``fin`` function that is like a ``finally`` clause.
171The final handler gets called, with no arguments, when the promise
172returned by ``getInputPromise()`` either returns a value or throws an
173error.  The value returned or error thrown by ``getInputPromise()``
174passes directly to ``outputPromise`` unless the final handler fails, and
175may be delayed if the final handler returns a promise.
176
177```javascript
178var outputPromise = getInputPromise()
179.fin(function () {
180    // close files, database connections, stop servers, conclude tests
181});
182```
183
184-   If the handler returns a value, the value is ignored
185-   If the handler throws an error, the error passes to ``outputPromise``
186-   If the handler returns a promise, ``outputPromise`` gets postponed.  The
187    eventual value or error has the same effect as an immediate return
188    value or thrown error: a value would be ignored, an error would be
189    forwarded.
190
191If you are writing JavaScript for modern engines only or using
192CoffeeScript, you may use `finally` instead of `fin`.
193
194### Chaining
195
196There are two ways to chain promises.  You can chain promises either
197inside or outside handlers.  The next two examples are equivalent.
198
199```javascript
200return getUsername()
201.then(function (username) {
202    return getUser(username)
203    .then(function (user) {
204        // if we get here without an error,
205        // the value returned here
206        // or the exception thrown here
207        // resolves the promise returned
208        // by the first line
209    })
210});
211```
212
213```javascript
214return getUsername()
215.then(function (username) {
216    return getUser(username);
217})
218.then(function (user) {
219    // if we get here without an error,
220    // the value returned here
221    // or the exception thrown here
222    // resolves the promise returned
223    // by the first line
224});
225```
226
227The only difference is nesting.  It’s useful to nest handlers if you
228need to capture multiple input values in your closure.
229
230```javascript
231function authenticate() {
232    return getUsername()
233    .then(function (username) {
234        return getUser(username);
235    })
236    // chained because we will not need the user name in the next event
237    .then(function (user) {
238        return getPassword()
239        // nested because we need both user and password next
240        .then(function (password) {
241            if (user.passwordHash !== hash(password)) {
242                throw new Error("Can't authenticate");
243            }
244        });
245    });
246}
247```
248
249
250### Combination
251
252You can turn an array of promises into a promise for the whole,
253fulfilled array using ``all``.
254
255```javascript
256return Q.all([
257    eventualAdd(2, 2),
258    eventualAdd(10, 20)
259]);
260```
261
262If you have a promise for an array, you can use ``spread`` as a
263replacement for ``then``.  The ``spread`` function “spreads” the
264values over the arguments of the fulfillment handler.  The rejection handler
265will get called at the first sign of failure.  That is, whichever of
266the recived promises fails first gets handled by the rejection handler.
267
268```javascript
269function eventualAdd(a, b) {
270    return Q.spread([a, b], function (a, b) {
271        return a + b;
272    })
273}
274```
275
276But ``spread`` calls ``all`` initially, so you can skip it in chains.
277
278```javascript
279return getUsername()
280.then(function (username) {
281    return [username, getUser(username)];
282})
283.spread(function (username, user) {
284});
285```
286
287The ``all`` function returns a promise for an array of values.  When this
288promise is fulfilled, the array contains the fulfillment values of the original
289promises, in the same order as those promises.  If one of the given promises
290is rejected, the returned promise is immediately rejected, not waiting for the
291rest of the batch.  If you want to wait for all of the promises to either be
292fulfilled or rejected, you can use ``allSettled``.
293
294```javascript
295Q.allSettled(promises)
296.then(function (results) {
297    results.forEach(function (result) {
298        if (result.state === "fulfilled") {
299            var value = result.value;
300        } else {
301            var reason = result.reason;
302        }
303    });
304});
305```
306
307
308### Sequences
309
310If you have a number of promise-producing functions that need
311to be run sequentially, you can of course do so manually:
312
313```javascript
314return foo(initialVal).then(bar).then(baz).then(qux);
315```
316
317However, if you want to run a dynamically constructed sequence of
318functions, you'll want something like this:
319
320```javascript
321var funcs = [foo, bar, baz, qux];
322
323var result = Q.resolve(initialVal);
324funcs.forEach(function (f) {
325    result = result.then(f);
326});
327return result;
328```
329
330You can make this slightly more compact using `reduce`:
331
332```javascript
333return funcs.reduce(function (soFar, f) {
334    return soFar.then(f);
335}, Q.resolve(initialVal));
336```
337
338Or, you could use th ultra-compact version:
339
340```javascript
341return funcs.reduce(Q.when, Q());
342```
343
344### Handling Errors
345
346One sometimes-unintuive aspect of promises is that if you throw an
347exception in the fulfillment handler, it will not be be caught by the error
348handler.
349
350```javascript
351return foo()
352.then(function (value) {
353    throw new Error("Can't bar.");
354}, function (error) {
355    // We only get here if "foo" fails
356});
357```
358
359To see why this is, consider the parallel between promises and
360``try``/``catch``. We are ``try``-ing to execute ``foo()``: the error
361handler represents a ``catch`` for ``foo()``, while the fulfillment handler
362represents code that happens *after* the ``try``/``catch`` block.
363That code then needs its own ``try``/``catch`` block.
364
365In terms of promises, this means chaining your rejection handler:
366
367```javascript
368return foo()
369.then(function (value) {
370    throw new Error("Can't bar.");
371})
372.fail(function (error) {
373    // We get here with either foo's error or bar's error
374});
375```
376
377### Progress Notification
378
379It's possible for promises to report their progress, e.g. for tasks that take a
380long time like a file upload. Not all promises will implement progress
381notifications, but for those that do, you can consume the progress values using
382a third parameter to ``then``:
383
384```javascript
385return uploadFile()
386.then(function () {
387    // Success uploading the file
388}, function (err) {
389    // There was an error, and we get the reason for error
390}, function (progress) {
391    // We get notified of the upload's progress as it is executed
392});
393```
394
395Like `fail`, Q also provides a shorthand for progress callbacks
396called `progress`:
397
398```javascript
399return uploadFile().progress(function (progress) {
400    // We get notified of the upload's progress
401});
402```
403
404### The End
405
406When you get to the end of a chain of promises, you should either
407return the last promise or end the chain.  Since handlers catch
408errors, it’s an unfortunate pattern that the exceptions can go
409unobserved.
410
411So, either return it,
412
413```javascript
414return foo()
415.then(function () {
416    return "bar";
417});
418```
419
420Or, end it.
421
422```javascript
423foo()
424.then(function () {
425    return "bar";
426})
427.done();
428```
429
430Ending a promise chain makes sure that, if an error doesn’t get
431handled before the end, it will get rethrown and reported.
432
433This is a stopgap. We are exploring ways to make unhandled errors
434visible without any explicit handling.
435
436
437### The Beginning
438
439Everything above assumes you get a promise from somewhere else.  This
440is the common case.  Every once in a while, you will need to create a
441promise from scratch.
442
443#### Using ``Q.fcall``
444
445You can create a promise from a value using ``Q.fcall``.  This returns a
446promise for 10.
447
448```javascript
449return Q.fcall(function () {
450    return 10;
451});
452```
453
454You can also use ``fcall`` to get a promise for an exception.
455
456```javascript
457return Q.fcall(function () {
458    throw new Error("Can't do it");
459});
460```
461
462As the name implies, ``fcall`` can call functions, or even promised
463functions.  This uses the ``eventualAdd`` function above to add two
464numbers.
465
466```javascript
467return Q.fcall(eventualAdd, 2, 2);
468```
469
470
471#### Using Deferreds
472
473If you have to interface with asynchronous functions that are callback-based
474instead of promise-based, Q provides a few shortcuts (like ``Q.nfcall`` and
475friends). But much of the time, the solution will be to use *deferreds*.
476
477```javascript
478var deferred = Q.defer();
479FS.readFile("foo.txt", "utf-8", function (error, text) {
480    if (error) {
481        deferred.reject(new Error(error));
482    } else {
483        deferred.resolve(text);
484    }
485});
486return deferred.promise;
487```
488
489Note that a deferred can be resolved with a value or a promise.  The
490``reject`` function is a shorthand for resolving with a rejected
491promise.
492
493```javascript
494// this:
495deferred.reject(new Error("Can't do it"));
496
497// is shorthand for:
498var rejection = Q.fcall(function () {
499    throw new Error("Can't do it");
500});
501deferred.resolve(rejection);
502```
503
504This is a simplified implementation of ``Q.delay``.
505
506```javascript
507function delay(ms) {
508    var deferred = Q.defer();
509    setTimeout(deferred.resolve, ms);
510    return deferred.promise;
511}
512```
513
514This is a simplified implementation of ``Q.timeout``
515
516```javascript
517function timeout(promise, ms) {
518    var deferred = Q.defer();
519    Q.when(promise, deferred.resolve);
520    Q.when(delay(ms), function () {
521        deferred.reject(new Error("Timed out"));
522    });
523    return deferred.promise;
524}
525```
526
527Finally, you can send a progress notification to the promise with
528``deferred.notify``.
529
530For illustration, this is a wrapper for XML HTTP requests in the browser. Note
531that a more [thorough][XHR] implementation would be in order in practice.
532
533[XHR]: https://github.com/montagejs/mr/blob/71e8df99bb4f0584985accd6f2801ef3015b9763/browser.js#L29-L73
534
535```javascript
536function requestOkText(url) {
537    var request = new XMLHttpRequest();
538    var deferred = Q.defer();
539
540    request.open("GET", url, true);
541    request.onload = onload;
542    request.onerror = onerror;
543    request.onprogress = onprogress;
544    request.send();
545
546    function onload() {
547        if (request.status === 200) {
548            deferred.resolve(request.responseText);
549        } else {
550            deferred.reject(new Error("Status code was " + request.status));
551        }
552    }
553
554    function onerror() {
555        deferred.reject(new Error("Can't XHR " + JSON.stringify(url)));
556    }
557
558    function onprogress(event) {
559        deferred.notify(event.loaded / event.total);
560    }
561
562    return deferred.promise;
563}
564```
565
566Below is an example of how to use this ``requestOkText`` function:
567
568```javascript
569requestOkText("http://localhost:3000")
570.then(function (responseText) {
571    // If the HTTP response returns 200 OK, log the response text.
572    console.log(responseText);
573}, function (error) {
574    // If there's an error or a non-200 status code, log the error.
575    console.error(error);
576}, function (progress) {
577    // Log the progress as it comes in.
578    console.log("Request progress: " + Math.round(progress * 100) + "%");
579});
580```
581
582### The Middle
583
584If you are using a function that may return a promise, but just might
585return a value if it doesn’t need to defer, you can use the “static”
586methods of the Q library.
587
588The ``when`` function is the static equivalent for ``then``.
589
590```javascript
591return Q.when(valueOrPromise, function (value) {
592}, function (error) {
593});
594```
595
596All of the other methods on a promise have static analogs with the
597same name.
598
599The following are equivalent:
600
601```javascript
602return Q.all([a, b]);
603```
604
605```javascript
606return Q.fcall(function () {
607    return [a, b];
608})
609.all();
610```
611
612When working with promises provided by other libraries, you should
613convert it to a Q promise.  Not all promise libraries make the same
614guarantees as Q and certainly don’t provide all of the same methods.
615Most libraries only provide a partially functional ``then`` method.
616This thankfully is all we need to turn them into vibrant Q promises.
617
618```javascript
619return Q.when($.ajax(...))
620.then(function () {
621});
622```
623
624If there is any chance that the promise you receive is not a Q promise
625as provided by your library, you should wrap it using a Q function.
626You can even use ``Q.invoke`` as a shorthand.
627
628```javascript
629return Q.invoke($, 'ajax', ...)
630.then(function () {
631});
632```
633
634
635### Over the Wire
636
637A promise can serve as a proxy for another object, even a remote
638object.  There are methods that allow you to optimistically manipulate
639properties or call functions.  All of these interactions return
640promises, so they can be chained.
641
642```
643direct manipulation         using a promise as a proxy
644--------------------------  -------------------------------
645value.foo                   promise.get("foo")
646value.foo = value           promise.put("foo", value)
647delete value.foo            promise.del("foo")
648value.foo(...args)          promise.post("foo", [args])
649value.foo(...args)          promise.invoke("foo", ...args)
650value(...args)              promise.fapply([args])
651value(...args)              promise.fcall(...args)
652```
653
654If the promise is a proxy for a remote object, you can shave
655round-trips by using these functions instead of ``then``.  To take
656advantage of promises for remote objects, check out [Q-Connection][].
657
658[Q-Connection]: https://github.com/kriskowal/q-connection
659
660Even in the case of non-remote objects, these methods can be used as
661shorthand for particularly-simple fulfillment handlers. For example, you
662can replace
663
664```javascript
665return Q.fcall(function () {
666    return [{ foo: "bar" }, { foo: "baz" }];
667})
668.then(function (value) {
669    return value[0].foo;
670});
671```
672
673with
674
675```javascript
676return Q.fcall(function () {
677    return [{ foo: "bar" }, { foo: "baz" }];
678})
679.get(0)
680.get("foo");
681```
682
683
684### Adapting Node
685
686If you're working with functions that make use of the Node.js callback pattern,
687Q provides a few useful utility functions for converting between them. The
688most straightforward are probably `Q.nfcall` and `Q.nfapply` ("Node function
689call/apply") for calling Node.js-style functions and getting back a promise:
690
691```javascript
692return Q.nfcall(FS.readFile, "foo.txt", "utf-8");
693return Q.nfapply(FS.readFile, ["foo.txt", "utf-8"]);
694```
695
696If you are working with methods, instead of simple functions, you can easily
697run in to the usual problems where passing a method to another function—like
698`Q.nfcall`—"un-binds" the method from its owner. To avoid this, you can either
699use `Function.prototype.bind` or some nice shortcut methods we provide:
700
701```javascript
702return Q.ninvoke(redisClient, "get", "user:1:id");
703return Q.npost(redisClient, "get", ["user:1:id"]);
704```
705
706You can also create reusable wrappers with `Q.denodeify` or `Q.nbind`:
707
708```javascript
709var readFile = Q.denodeify(FS.readFile);
710return readFile("foo.txt", "utf-8");
711
712var redisClientGet = Q.nbind(redisClient.get, redisClient);
713return redisClientGet("user:1:id");
714```
715
716Finally, if you're working with raw deferred objects, there is a
717`makeNodeResolver` method on deferreds that can be handy:
718
719```javascript
720var deferred = Q.defer();
721FS.readFile("foo.txt", "utf-8", deferred.makeNodeResolver());
722return deferred.promise;
723```
724
725### Long Stack Traces
726
727Q comes with optional support for “long stack traces,” wherein the `stack`
728property of `Error` rejection reasons is rewritten to be traced along
729asynchronous jumps instead of stopping at the most recent one. As an example:
730
731```js
732function theDepthsOfMyProgram() {
733  Q.delay(100).done(function explode() {
734    throw new Error("boo!");
735  });
736}
737
738theDepthsOfMyProgram();
739```
740
741usually would give a rather unhelpful stack trace looking something like
742
743```
744Error: boo!
745    at explode (/path/to/test.js:3:11)
746    at _fulfilled (/path/to/test.js:q:54)
747    at resolvedValue.promiseDispatch.done (/path/to/q.js:823:30)
748    at makePromise.promise.promiseDispatch (/path/to/q.js:496:13)
749    at pending (/path/to/q.js:397:39)
750    at process.startup.processNextTick.process._tickCallback (node.js:244:9)
751```
752
753But, if you turn this feature on by setting
754
755```js
756Q.longStackSupport = true;
757```
758
759then the above code gives a nice stack trace to the tune of
760
761```
762Error: boo!
763    at explode (/path/to/test.js:3:11)
764From previous event:
765    at theDepthsOfMyProgram (/path/to/test.js:2:16)
766    at Object.<anonymous> (/path/to/test.js:7:1)
767```
768
769Note how you can see the the function that triggered the async operation in the
770stack trace! This is very helpful for debugging, as otherwise you end up getting
771only the first line, plus a bunch of Q internals, with no sign of where the
772operation started.
773
774This feature does come with somewhat-serious performance and memory overhead,
775however. If you're working with lots of promises, or trying to scale a server
776to many users, you should probably keep it off. But in development, go for it!
777
778## Reference
779
780A method-by-method [Q API reference][reference] is available on the wiki.
781
782[reference]: https://github.com/kriskowal/q/wiki/API-Reference
783
784## More Examples
785
786A growing [examples gallery][examples] is available on the wiki, showing how Q
787can be used to make everything better. From XHR to database access to accessing
788the Flickr API, Q is there for you.
789
790[examples]: https://github.com/kriskowal/q/wiki/Examples-Gallery
791
792## Tests
793
794You can view the results of the Q test suite [in your browser][tests]!
795
796[tests]: https://rawgithub.com/kriskowal/q/master/spec/q-spec.html
797
798---
799
800Copyright 2009-2012 Kristopher Michael Kowal
801MIT License (enclosed)
802
Note: See TracBrowser for help on using the repository browser.