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

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

Update node modules

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