Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 2309 lines (1639 sloc) 84.164 kb
8d43875 @briancavalier Moving api docs to straight markdown file in docs dir. Trimming down an...
briancavalier authored
1 API
2 ===
3
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
4 1. Core
ca9523d @briancavalier Try arguments only
briancavalier authored
5 * [when(x)](#when)
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
6 * [when(x, f)](#when)
ca9523d @briancavalier Try arguments only
briancavalier authored
7 * [when.try(f, ...args)](#whentry)
0bb0cdc @briancavalier Add a few layout variation examples
briancavalier authored
8 * [when.lift(f)](#whenlift)
9 * [when.join(...promises)](#whenjoin)
ca9523d @briancavalier Try arguments only
briancavalier authored
10 * [when.promise(resolver)](#whenpromise)
11 * [when.resolve(x)](#whenresolve)
12 * [when.reject(error)](#whenreject)
13 * [when.defer()](#whendefer)
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
14 * [when.isPromiseLike(x)](#whenispromiselike)
e4b55bd @briancavalier Add TOC links to updated docs
briancavalier authored
15 1. Promise
ca9523d @briancavalier Try arguments only
briancavalier authored
16 * [promise.done(handleResult, handleError)](#promisedone)
17 * [promise.then(onFulfilled)](#promisethen)
18 * [promise.spread(onFulfilledArray)](#promisespread)
29abd5f @briancavalier Add promise.fold to TOC, minor cleanup
briancavalier authored
19 * [promise.fold(combine, promise2)](#promisefold)
ca9523d @briancavalier Try arguments only
briancavalier authored
20 * [promise.catch(onRejected)](#promisecatch)
21 * [promise.finally(cleanup)](#promisefinally)
22 * [promise.yield(x)](#promiseyield)
23 * [promise.else(x)](#promiseelse)
24 * [promise.tap(onFulfilledSideEffect)](#promisetap)
25 * [promise.delay(milliseconds)](#promisedelay)
15b0ef7 @scothis Allow custom rejection reason for promise.timeout()
scothis authored
26 * [promise.timeout(milliseconds, reason)](#promisetimeout)
ca9523d @briancavalier Try arguments only
briancavalier authored
27 * [promise.inspect()](#promiseinspect)
28 * [promise.with(thisArg)](#promisewith)
29 * [promise.progress(onProgress)](#promiseprogress)
e4b55bd @briancavalier Add TOC links to updated docs
briancavalier authored
30 1. Arrays
e23b7db @briancavalier Add params to all funcs in TOC
briancavalier authored
31 * [when.all(array)](#whenall)
32 * [when.settle(array)](#whensettle)
33 * [when.map(array, mapper)](#whenmap)
889d8d2 @briancavalier Add when.filter. Pass array indices in when.map and when.filter, keys
briancavalier authored
34 * [when.filter(array, predicate)](#whenfilter)
e23b7db @briancavalier Add params to all funcs in TOC
briancavalier authored
35 * [when.reduce(array, reducer)](#whenreduce)
36 * [when.reduceRight(array, reducer)](#whenreduceright)
e4b55bd @briancavalier Add TOC links to updated docs
briancavalier authored
37 1. Array Races
e23b7db @briancavalier Add params to all funcs in TOC
briancavalier authored
38 * [when.any(array)](#whenany)
39 * [when.some(array, n)](#whensome)
8bfe7ce @briancavalier Update verbage around iterate/unfold
briancavalier authored
40 1. Infinite Promise Sequences
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
41 * [when.iterate(f, condition, handler, seed)](#wheniterate)
42 * [when.unfold(f, condition, handler, seed)](#whenunfold)
e4b55bd @briancavalier Add TOC links to updated docs
briancavalier authored
43 1. Objects
44 * when/keys
e23b7db @briancavalier Add params to all funcs in TOC
briancavalier authored
45 * [keys.all(object)](#whenkeys-all)
46 * [keys.map(object, mapper)](#whenkeys-map)
e4b55bd @briancavalier Add TOC links to updated docs
briancavalier authored
47 1. Functions
48 * when/function
e23b7db @briancavalier Add params to all funcs in TOC
briancavalier authored
49 * [fn.lift(f)](#fnlift)
50 * [fn.liftAll(object)](#fnliftall)
51 * [fn.call(f, ...args)](#fncall)
52 * [fn.apply(f, argsArray)](#fnapply)
0174a12 @briancavalier Add when/poll link to TOC. Reorder a bit
briancavalier authored
53 * when/node
54 * [node.lift(nodeFunction)](#nodelift)
55 * [node.liftAll(object)](#nodeliftall)
56 * [node.call(nodeFunction, ...args)](#nodecall)
57 * [node.apply(nodeFunction, argsArray)](#nodeapply)
1dff5e1 @briancavalier Fix #274. Add missing TOC links, plus other minor api doc cleanup
briancavalier authored
58 * [node.bindCallback(promise, nodeback)](#nodebindcallback)
59 * [node.liftCallback(callback)](#nodeliftcallback)
60 * [node.createCallback(resolver)](#nodecreatecallback)
6ccc429 @jamlen Add example of supporting both promises and node-style callbacks.
jamlen authored
61 * [Support promises and node-style functions](#support-promises-and-node-style-callback-functions)
e4b55bd @briancavalier Add TOC links to updated docs
briancavalier authored
62 * when/callbacks
e23b7db @briancavalier Add params to all funcs in TOC
briancavalier authored
63 * [callbacks.lift(asyncFunction)](#callbackslift)
64 * [callbacks.liftAll(object)](#callbacksliftall)
65 * [callbacks.call(asyncFunction, ...args)](#callbackscall)
66 * [callbacks.apply(asyncFunction, argsArray)](#callbacksapply)
e4b55bd @briancavalier Add TOC links to updated docs
briancavalier authored
67 1. [ES6 generators](#es6-generators)
68 * when/generator
e23b7db @briancavalier Add params to all funcs in TOC
briancavalier authored
69 * [generator.lift(g)](#generatorlift)
70 * [generator.call(g, ...args)](#generatorcall)
71 * [generator.apply(g, argsArray)](#generatorapply)
72 1. Task Execution
73 * [when/sequence(tasks, ...args)](#whensequence)
74 * [when/pipeline(tasks, ...args)](#whenpipeline)
75 * [when/parallel(tasks, ...args)](#whenparallel)
0174a12 @briancavalier Add when/poll link to TOC. Reorder a bit
briancavalier authored
76 * [when/poll(task, interval, condition [, initialDelay])](#whenpoll)
e23b7db @briancavalier Add params to all funcs in TOC
briancavalier authored
77 1. Limiting Concurrency
78 * [when/guard(condition, f)](#whenguard)
9c45880 @briancavalier Move guard examples up. Add Guard conditions to TOC
briancavalier authored
79 * [Guard conditions](#guard-conditions)
fffafd5 @jodal Fix broken link in API docs ToC
jodal authored
80 1. [Error types](#error-types)
9eff801 @briancavalier Move when/monitor docs to main docs, simplify README and link to docs
briancavalier authored
81 1. [Debugging promises](#debugging-promises)
f3057ee @briancavalier Update changelog, add upgrading to 3.0 section to docs
briancavalier authored
82 1. [Upgrading to 3.0 from 2.x](#upgrading-to-30-from-2x)
da12855 @briancavalier Deprecate progress, provide example of refactoring w/promise.tap
briancavalier authored
83 1. [Refactoring progress](#refactoring-progress)
f9dae39 @briancavalier API doc update
briancavalier authored
84
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
85 # Core
86
a035e59 @briancavalier Added docs for when.join, plus more docs cleanup
briancavalier authored
87 ## when()
f9dae39 @briancavalier API doc update
briancavalier authored
88
c7b882a @briancavalier Added when/timeout and when/delay
briancavalier authored
89 ```js
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
90 var promise = when(x);
c7b882a @briancavalier Added when/timeout and when/delay
briancavalier authored
91 ```
8d43875 @briancavalier Moving api docs to straight markdown file in docs dir. Trimming down an...
briancavalier authored
92
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
93 Get a trusted promise for `x`. If `x` is:
18859e8 @briancavalier Improve when() and .then() docs and include basic information about hand...
briancavalier authored
94
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
95 * a value, returns a promise fulfilled with `x`
96 * a promise, returns `x`.
97 * a foreign thenable, returns a promise that follows `x`
18859e8 @briancavalier Improve when() and .then() docs and include basic information about hand...
briancavalier authored
98
99
c7b882a @briancavalier Added when/timeout and when/delay
briancavalier authored
100 ```js
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
101 var transformedPromise = when(x, f);
8d43875 @briancavalier Moving api docs to straight markdown file in docs dir. Trimming down an...
briancavalier authored
102 ```
103
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
104 Get a trusted promise by transforming `x` with `f`. If `x` is
105
106 * a value, returns a promise fulfilled with `f(x)`
107 * a promise or thenable, returns a promise that
108 * if `x` fulfills, will fulfill with the result of calling `f` with `x`'s fulfillment value.
109 * if `x` rejects, will reject with the same reason as `x`
ac1963c @briancavalier See #70. Add info about when() always returning a when.js promise, which...
briancavalier authored
110
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
111 `when()` accepts any promise that provides a *thenable* promise--any object that provides a `.then()` method, even promises that aren't fully Promises/A+ compliant, such as jQuery's Deferred. It will assimilate such promises and make them behave like Promises/A+.
fc0ed69 @briancavalier Tweaking api doc order
briancavalier authored
112
e4b55bd @briancavalier Add TOC links to updated docs
briancavalier authored
113 ## when.try
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
114
5e18014 @briancavalier Add when.try/when.lift examples
briancavalier authored
115 **ALIAS:** when.attempt() for non-ES5 environments
116
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
117 ```js
118 var promise = when.try(f /*, arg1, arg2, ...*/);
119 ```
120
121 Calls `f` with the supplied arguments, returning a promise for the result. The arguments may be promises, in which case, `f` will be called after they have fulfilled. The returned promise will fulfill with the successful result of calling `f`. If any argument is a rejected promise, or if `f` fails by throwing or returning a rejected promise, the returned promise will also be rejected.
122
5e18014 @briancavalier Add when.try/when.lift examples
briancavalier authored
123 This can be a great way to kick off a promise chain when you want to return a promise, rather than creating a one manually.
124
125 ```js
126 // Try to parse the JSON, capture any failures in the returned promise
127 // (This will never throw)
128 return when.try(JSON.parse, jsonString);
129 ```
130
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
131 ### See also:
e4b55bd @briancavalier Add TOC links to updated docs
briancavalier authored
132 * [when.lift](#whenlift)
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
133 * [when/node call](#nodecall)
134 * [when/node apply](#nodeapply)
fc0ed69 @briancavalier Tweaking api doc order
briancavalier authored
135
e4b55bd @briancavalier Add TOC links to updated docs
briancavalier authored
136 ## when.lift
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
137
138 ```js
139 var g = when.lift(f);
140 ```
8d43875 @briancavalier Moving api docs to straight markdown file in docs dir. Trimming down an...
briancavalier authored
141
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
142 Creates a "promisified" version of `f`, which always returns promises (`g` will never throw) and accepts promises or values as arguments. In other words, calling `g(x, y z)` is like calling `when.try(f, x, y, z)` with the added convenience that once you've created `g` you can call it repeatedly or pass it around like any other function. In addition, `g`'s thisArg will behave in a predictable way, like any other function (you can `.bind()` it, or use `.call()` or `.apply()`, etc.).
143
5e18014 @briancavalier Add when.try/when.lift examples
briancavalier authored
144 Like `when.try`, lifting functions provides a convenient way start promise chains without having to explicitly create promises, e.g. `new Promise`
145
146 ```js
147 // Call parse as often as you need now.
148 // It will always return a promise, and will never throw
149 // Errors will be captured in the returned promise.
150 var jsonParse = when.lift(JSON.parse);
151
152 // Now use it wherever you need
153 return jsonParse(jsonString);
154 ```
155
156 `when.lift` correctly handles `this`, so object methods can be lifted as well:
157
158 ```js
159 var parser = {
160 reviver: ...
161 parse: when.lift(function(str) {
162 return JSON.parse(str, this.reviver);
163 });
164 };
165
166 // Now use it wherever you need
167 return parser.parse(jsonString);
168 ```
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
169
170 ### See also:
171 * [when.try](#whentry)
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
172 * [when/node lift](#nodelift)
173 * [when/node liftAll](#nodeliftall)
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
174
e4b55bd @briancavalier Add TOC links to updated docs
briancavalier authored
175 ## when.join
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
176
177 ```js
178 var joinedPromise = when.join(promiseOrValue1, promiseOrValue2, ...);
179 ```
180
181 Return a promise that will fulfill only once *all* the inputs have fulfilled. The value of the returned promise will be an array containing the values of each of the inputs.
182
183 If any of the input promises is rejected, the returned promise will be rejected with the reason from the first one that is rejected.
184
185 ```js
186 // largerPromise will resolve to the greater of two eventual values
187 var largerPromise = when.join(promise1, promise2).then(function (values) {
188 return values[0] > values[1] ? values[0] : values[1];
189 });
190 ```
191
192 ### See also:
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
193 * [when.all](#whenall) - resolving an Array of promises
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
194
195 ## when.promise
196
197 ```js
198 var promise = when.promise(resolver);
199 ```
200
201 Create a [Promise](#promise), whose fate is determined by running the supplied resolver function. The resolver function will be called synchronously, with 3 arguments:
202
203 ```js
204 var promise = when.promise(function(resolve, reject, notify) {
205 // Do some work, possibly asynchronously, and then
da12855 @briancavalier Deprecate progress, provide example of refactoring w/promise.tap
briancavalier authored
206 // resolve or reject.
207
208 // DEPRECATED: You can notify of progress events
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
209 // along the way if you want/need.
210
211 resolve(awesomeResult);
212 // or resolve(anotherPromise);
213 // or reject(nastyError);
214 });
215 ```
216
217 * `resolve(promiseOrValue)` - Primary function that seals the fate of the returned promise. Accepts either a non-promise value, or another promise.
218 * When called with a non-promise value, fulfills `promise` with that value.
219 * When called with another promise, e.g. `resolve(otherPromise)`, `promise`'s fate will be equivalent to that that of `otherPromise`.
220 * `reject(reason)` - function that rejects `promise`.
da12855 @briancavalier Deprecate progress, provide example of refactoring w/promise.tap
briancavalier authored
221 * `notify(update)` - **DEPRECATED** function that issues progress events for `promise`. See [Refactoring progress](#refactoring-progress) for more info.
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
222
223 ## when.resolve
224
225 ```js
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
226 var resolved = when.resolve(x);
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
227 ```
228
161a607 @briancavalier Add ES6 Promise shim docs
briancavalier authored
229 Get a promise for the supplied `x`. If `x` is already a trusted promise, it is returned. If `x` is a value, the returned promise will be fulfilled with `x`. If `x` is a thenable, the returned promise will follow `x`, adopting its eventual state (fulfilled or rejected).
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
230
231 ## when.reject
232
233 ```js
234 var rejected = when.reject(error);
235 ```
236
237 Create a rejected promise with the supplied error as the rejection reason.
238
239 **DEPRECATION WARNING:** In when.js 2.x, error is allowed to be a promise for an error. In when.js 3.0, error will always be used verbatim as the rejection reason, even if it is a promise.
240
e4b55bd @briancavalier Add TOC links to updated docs
briancavalier authored
241 ## when.defer
242
243 ```js
244 var deferred = when.defer();
c1ea9b5 @briancavalier Explicitly discourage the use of when.defer, and point people at alterna...
briancavalier authored
245 ```
246
247 **Note:** The use of `when.defer` is discouraged. In most cases, using [`when.promise`](#whenpromise), [`when.try`](#whentry), or [`when.lift`](#whenlift) provides better separation of concerns.
248
249 Create a `{promise, resolve, reject, notify}` tuple. In certain (rare) scenarios it can be convenient to have access to both the `promise` and it's associated resolving functions.
250
251 The deferred API:
252
253 ```js
e4b55bd @briancavalier Add TOC links to updated docs
briancavalier authored
254 var promise = deferred.promise;
c1ea9b5 @briancavalier Explicitly discourage the use of when.defer, and point people at alterna...
briancavalier authored
255
256 // Resolve the promise, x may be a promise or non-promise
257 deferred.resolve(x)
258
259 // Reject the promise with error as the reason
260 deferred.reject(error)
261
da12855 @briancavalier Deprecate progress, provide example of refactoring w/promise.tap
briancavalier authored
262 // DEPRECATED Notify promise consumers of a progress update
c1ea9b5 @briancavalier Explicitly discourage the use of when.defer, and point people at alterna...
briancavalier authored
263 deferred.notify(x)
e4b55bd @briancavalier Add TOC links to updated docs
briancavalier authored
264 ```
265
c1ea9b5 @briancavalier Explicitly discourage the use of when.defer, and point people at alterna...
briancavalier authored
266 Note that `resolve`, `reject`, and `notify` all become no-ops after either `resolve` or `reject` has been called the first time.
e4b55bd @briancavalier Add TOC links to updated docs
briancavalier authored
267
fac32f3 @briancavalier Clean up defer docs a bit more
briancavalier authored
268 One common use case for creating a deferred is adapting callback-based functions to promises. In those cases, it's preferable to use the [when/callbacks](#asynchronous-functions) module to [call](#callbackscall) or [lift](#callbackslift) the callback-based functions instead. For adapting node-style async functions, use the [when/node](#node-style-asynchronous-functions) module.
e4b55bd @briancavalier Add TOC links to updated docs
briancavalier authored
269
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
270 ## when.isPromiseLike
271
272 ```js
273 var is = when.isPromiseLike(x);
274 ```
275
276 Return true if `x` is an object or function with a `then` method. It does not distinguish trusted when.js promises from other "thenables" (e.g. from some other promise implementation).
277
278 Using `isPromiseLike` is discouraged. In cases where you have an `x` and don't know if it's a promise, typically the best thing to do is to cast it: `var trustedPromise = when(x);` and then use `trustedPromise`.
279
280
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
281 # Promise
282
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
283 A promise is a proxy for a value that isn't available yet allowing you to interact with it as if it is.
2616c27 @briancavalier #53 Add info about .then returning a new promise to API docs
briancavalier authored
284
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
285 ## promise.done
286
287 ```js
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
288 promise.done(handleValue); // returns undefined
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
289 ```
290
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
291 The simplest API for interacting with a promise, `done` consumes the promise's ultimate value if it fulfills, or causes a fatal error with a loud stack trace if it rejects.
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
292
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
293 ```js
bda09fb @briancavalier Deprecate then's third argument
briancavalier authored
294 promise.done(handleValue, handleError); // returns undefined
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
295 ```
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
296
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
297 Consume the promise's ultimate value if the promise fulfills, or handle the ultimate error. It will cause a fatal error if either `handleValue` or `handleError` throw or return a rejected promise.
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
298
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
299 Since `done`'s purpose is consumption rather than transformation, `done` always returns `undefined`.
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
300
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
301 One golden rule of promise error handling is:
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
302
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
303 Either `return` the promise, thereby *passing the error-handling buck* to the caller, or call `done` and *assuming responsibility for errors*.
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
304
0bb0cdc @briancavalier Add a few layout variation examples
briancavalier authored
305 ### See also
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
306 * [promise.then vs. promise.done](#promisethen-vs-promisedone)
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
307 * [promise.then](#promisethen)
308
309 ## promise.then
f9dae39 @briancavalier API doc update
briancavalier authored
310
2616c27 @briancavalier #53 Add info about .then returning a new promise to API docs
briancavalier authored
311 ```js
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
312 var transformedPromise = promise.then(onFulfilled);
313 ```
314
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
315 [Promises/A+ `then`](http://promisesaplus.com). *Transforms* a promise's value by applying a function to the promise's fulfillment value. Returns a new promise for the transformed result.
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
316
317 ```js
bda09fb @briancavalier Deprecate then's third argument
briancavalier authored
318 var transformedPromise = promise.then(onFulfilled, onRejected);
319 ```
320
321 `then` may also be used to recover from intermediate errors. However, [`promise.catch`](#promisecatch) is almost always a better, and more readable choice. When `onRejected` is provided, it only handles errors from `promise`, and *will not* handle errors thrown by `onFulfilled`. Compare:
322
323 ```js
324 // Using only then(): onRejected WILL NOT handle errors thrown by onFulfilled
325 var transformedPromise = promise
326 .then(onFulfilled, onRejected);
327
328 // Using catch(): onRejected will handled errors thrown by onFulfilled
329 var transformedPromise = promise
330 .then(onFulfilled)
331 .catch(onRejected);
332
333 // Using catch() is equivalent to:
334 var transformedPromise = promise
335 .then(onFulfilled)
336 .then(void 0, onRejected);
8d43875 @briancavalier Moving api docs to straight markdown file in docs dir. Trimming down an...
briancavalier authored
337 ```
338
da12855 @briancavalier Deprecate progress, provide example of refactoring w/promise.tap
briancavalier authored
339 **DEPRECATED**: Progress events are deprecated and will be removed in a future release. Until that release. See [Refactoring progress](#refactoring-progress).
bda09fb @briancavalier Deprecate then's third argument
briancavalier authored
340
341 ```js
da12855 @briancavalier Deprecate progress, provide example of refactoring w/promise.tap
briancavalier authored
342 // Deprecated use of then() and promise.progress() to listen for progress events
bda09fb @briancavalier Deprecate then's third argument
briancavalier authored
343
da12855 @briancavalier Deprecate progress, provide example of refactoring w/promise.tap
briancavalier authored
344 var transformedPromise = promise.then(onFulfilled, onRejected, onProgress);
345 // or
bda09fb @briancavalier Deprecate then's third argument
briancavalier authored
346 var transformedPromise = promise
347 .progress(onProgress)
348 .then(onFulfilled)
349 .catch(onRejected)
350 ```
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
351
352 `then` arranges for:
18859e8 @briancavalier Improve when() and .then() docs and include basic information about hand...
briancavalier authored
353
354 * `onFulfilled` to be called with the value after `promise` is fulfilled, or
355 * `onRejected` to be called with the rejection reason after `promise` is rejected.
da12855 @briancavalier Deprecate progress, provide example of refactoring w/promise.tap
briancavalier authored
356 * **DEPRECATED**: `onProgress` to be called with any progress updates issued by `promise`. See [Refactoring progress](#refactoring-progress).
2616c27 @briancavalier #53 Add info about .then returning a new promise to API docs
briancavalier authored
357
358 A promise makes the following guarantees about handlers registered in the same call to `.then()`:
359
c3f3d36 @briancavalier Update terminology in api doc
briancavalier authored
360 1. Only one of `onFulfilled` or `onRejected` will be called, never both.
361 1. `onFulfilled` and `onRejected` will never be called more than once.
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
362 1. `onProgress` may be called zero or more times.
2616c27 @briancavalier #53 Add info about .then returning a new promise to API docs
briancavalier authored
363
a6120b3 @briancavalier Add cross refs for done and then
briancavalier authored
364 ### See also
fb395a9 @briancavalier Fix link
briancavalier authored
365 * [Promises/A+](http://promisesaplus.com) for extensive information on the behavior of `then`.
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
366 * [promise.done](#promisedone)
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
367 * [promise.spread](#promisespread)
bda09fb @briancavalier Deprecate then's third argument
briancavalier authored
368 * [promise.progress](#promiseprogress)
163965c @briancavalier Fix doc typo, add link to Promises/A+ for more info on behavior of then(...
briancavalier authored
369
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
370 ## promise.spread
d08bbb8 @briancavalier Add jsdoc and api docs for promise.done. Expand Debugging Promises
briancavalier authored
371
372 ```js
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
373 var transformedPromise = promise.spread(onFulfilledArray);
d08bbb8 @briancavalier Add jsdoc and api docs for promise.done. Expand Debugging Promises
briancavalier authored
374 ```
375
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
376 Similar to [`then`](#promisethen), but calls `onFulfilledArray` with promise's value, which is assumed to be an array, as its argument list. It's essentially a shortcut for:
3aa3ef5 @briancavalier Finish docs for done()
briancavalier authored
377
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
378 ```js
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
379 // Wrapping onFulfilledArray
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
380 promise.then(function(array) {
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
381 return onFulfilledArray.apply(undefined, array);
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
382 });
383 ```
8d43875 @briancavalier Moving api docs to straight markdown file in docs dir. Trimming down an...
briancavalier authored
384
cf21190 @jenius add documentation
jenius authored
385 ## promise.fold
386
387 ```js
6ac7b07 @briancavalier Revise promise.fold api docs slightly
briancavalier authored
388 var resultPromise = promise2.fold(combine, promise1)
cf21190 @jenius add documentation
jenius authored
389 ```
390
6ac7b07 @briancavalier Revise promise.fold api docs slightly
briancavalier authored
391 Combine `promise1` and `promise2` to produce a `resultPromise`. The `combine` function will be called once both `promise1` and `promise2` have fulfilled: `combine(promise1, promise2)`, and like `then` et al, it may return a promise or a value.
392
393 Just as `promise.then` allows you to easily re-use existing one-argument functions to transform promises, `promise.fold` allows you to reuse two-argument functions. It can also be useful when you need to thread one extra piece of information into a promise chain, *without* having to capture it in a closure or use `promise.with`.
d75ab1c @briancavalier Update versions. Expand promise.fold docs. For now, support sparse array...
briancavalier authored
394
395 For, example, with an existing `sum` function, you can easily sum the value of two promises:
396
397 ```js
398 function sum(x, y) {
399 return x + y;
400 }
401
6ac7b07 @briancavalier Revise promise.fold api docs slightly
briancavalier authored
402 var promiseFor3 = when(3);
403
404 var promiseFor5 = promiseFor3.fold(sum, promiseFor2);
405
406 // Of course, it accepts values as well:
407 var promiseFor5 = promiseFor3.fold(sum, 2);
d75ab1c @briancavalier Update versions. Expand promise.fold docs. For now, support sparse array...
briancavalier authored
408 ```
409
410 Or get object properties or array values:
411
412 ```js
6ac7b07 @briancavalier Revise promise.fold api docs slightly
briancavalier authored
413 function get(key, object) {
414 return object[key];
d75ab1c @briancavalier Update versions. Expand promise.fold docs. For now, support sparse array...
briancavalier authored
415 }
416
29abd5f @briancavalier Add promise.fold to TOC, minor cleanup
briancavalier authored
417 when({ name: 'Bob' })
d75ab1c @briancavalier Update versions. Expand promise.fold docs. For now, support sparse array...
briancavalier authored
418 .fold(get, 'name')
419 .done(console.log); // logs 'Bob'
420
29abd5f @briancavalier Add promise.fold to TOC, minor cleanup
briancavalier authored
421 when(['a', 'b', 'c'])
d75ab1c @briancavalier Update versions. Expand promise.fold docs. For now, support sparse array...
briancavalier authored
422 .fold(get, 1)
423 .done(console.log); // logs 'b'
424 ```
425
426 In both cases, `sum` and `get` are generic, *reusable* functions, and no closures were required.
cf21190 @jenius add documentation
jenius authored
427
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
428 ## promise.catch
a6120b3 @briancavalier Add cross refs for done and then
briancavalier authored
429
3c118cb @briancavalier Update docs with catch/finally aliases
briancavalier authored
430 **ALIAS:** otherwise() for non-ES5 environments
f9dae39 @briancavalier API doc update
briancavalier authored
431
8d43875 @briancavalier Moving api docs to straight markdown file in docs dir. Trimming down an...
briancavalier authored
432 ```js
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
433 var recoveredPromise = promise.catch(onRejected);
8d43875 @briancavalier Moving api docs to straight markdown file in docs dir. Trimming down an...
briancavalier authored
434 ```
435
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
436 In it's simplest form, `catch` arranges to call `onRejected` on the promise's rejection reason if it is rejected.
18859e8 @briancavalier Improve when() and .then() docs and include basic information about hand...
briancavalier authored
437
438 ```js
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
439 var recoveredPromise = promise.catch(predicate, onRejected);
18859e8 @briancavalier Improve when() and .then() docs and include basic information about hand...
briancavalier authored
440 ```
fc0ed69 @briancavalier Tweaking api doc order
briancavalier authored
441
0bb0cdc @briancavalier Add a few layout variation examples
briancavalier authored
442 If you also supply a `predicate`, you can `catch` only errors matching the predicate. This allows much more precise error handling. The `predicate` can be either an `Error` constructor, like `TypeError`, `ReferenceError`, or any custom error type (its `prototype` must be `instanceof Error`), or it can be a function that returns a boolean.
443
444 ```js
445 promise.then(function() {
446 throw new CustomError('oops!');
447 }).catch(CustomError, function(e) {
448 // Only catch CustomError instances
449 // all other types of errors will propagate automatically
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
450 }).catch(function(e) {
451 // Catch other errors
0bb0cdc @briancavalier Add a few layout variation examples
briancavalier authored
452 })
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
453 ```
454
455 Doing this in synchronous code is more clumsy, requiring `instanceof` checks inside a `catch` block:
456
457 ```js
458 try {
459 throw new CustomError('oops!');
460 } catch(e) {
461 if(e instanceof CustomError) {
462 // Handler CustomError instances
463 } else {
464 // Handle other errors
465 }
466 }
467 ```
0bb0cdc @briancavalier Add a few layout variation examples
briancavalier authored
468
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
469 ### See also:
470 * [promise.finally](#promisefinally)
471
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
472 ## promise.finally
3c118cb @briancavalier Update docs with catch/finally aliases
briancavalier authored
473
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
474 **ALIAS:** `ensure()` for non-ES5 environments
fc0ed69 @briancavalier Tweaking api doc order
briancavalier authored
475
c7b882a @briancavalier Added when/timeout and when/delay
briancavalier authored
476 ```js
8210980 @briancavalier Fix and improve promise.finally docs. See #320
briancavalier authored
477 var promise2 = promise1.finally(cleanup);
fc0ed69 @briancavalier Tweaking api doc order
briancavalier authored
478 ```
479
8210980 @briancavalier Fix and improve promise.finally docs. See #320
briancavalier authored
480 Finally allows you to execute "cleanup" type tasks in a promise chain. It arranges for `cleanup` to be called, *with no arguments*, when `promise1` is either fulfilled or rejected. It behaves similarly the synchronous `finally` statement:
481
482 * If `promise1` fulfills, and `cleanup` returns successfully, `promise2` will fulfill with the same value as `promise1`.
483 * If `promise1` rejects, and `cleanup` returns successfully, `promise2` will reject with the same reason as `promise1`.
484 * If `promise1` rejects, and `cleanup` throws or returns a rejected promise, `promise2` will reject with the thrown exception or rejected promise's reason.
9e29a66 @briancavalier Close #103. Implement promise.ensure, deprecate promise.always. API docs...
briancavalier authored
485
3c118cb @briancavalier Update docs with catch/finally aliases
briancavalier authored
486 When combined with `promise.catch`, `promise.finally` allows you to write code that is similar to the familiar synchronous `catch`/`finally` pair. Consider the following synchronous code:
18859e8 @briancavalier Improve when() and .then() docs and include basic information about hand...
briancavalier authored
487
488 ```js
9e29a66 @briancavalier Close #103. Implement promise.ensure, deprecate promise.always. API docs...
briancavalier authored
489 try {
490 return doSomething(x);
491 } catch(e) {
492 return handleError(e);
493 } finally {
494 cleanup();
495 }
496 ```
497
3c118cb @briancavalier Update docs with catch/finally aliases
briancavalier authored
498 Using `promise.finally`, similar asynchronous code (with `doSomething()` that returns a promise) can be written:
9e29a66 @briancavalier Close #103. Implement promise.ensure, deprecate promise.always. API docs...
briancavalier authored
499
500 ```js
501 return doSomething()
3c118cb @briancavalier Update docs with catch/finally aliases
briancavalier authored
502 .catch(handleError)
503 .finally(cleanup);
18859e8 @briancavalier Improve when() and .then() docs and include basic information about hand...
briancavalier authored
504 ```
505
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
506 ### See also:
507 * [promise.catch](#promisecatch) - intercept a rejected promise
508
509 ## promise.yield
4af946a @briancavalier Docs for promise.yield
briancavalier authored
510
511 ```js
1866056 @skiadas Clarify the behavior of promise.yield. Fixes #164
skiadas authored
512 originalPromise.yield(promiseOrValue);
4af946a @briancavalier Docs for promise.yield
briancavalier authored
513 ```
514
1866056 @skiadas Clarify the behavior of promise.yield. Fixes #164
skiadas authored
515 Returns a new promise:
4af946a @briancavalier Docs for promise.yield
briancavalier authored
516
1866056 @skiadas Clarify the behavior of promise.yield. Fixes #164
skiadas authored
517 1. If `originalPromise` is rejected, the returned promise will be rejected with the same reason
518 2. If `originalPromise` is fulfilled, then it "yields" the resolution of the returned promise to promiseOrValue, namely:
519 1. If `promiseOrValue` is a value, the returned promise will be fulfilled with `promiseOrValue`
520 2. If `promiseOrValue` is a promise, the returned promise will be:
521 - fulfilled with the fulfillment value of `promiseOrValue`, or
522 - rejected with the rejection reason of `promiseOrValue`
4af946a @briancavalier Docs for promise.yield
briancavalier authored
523
9e29a66 @briancavalier Close #103. Implement promise.ensure, deprecate promise.always. API docs...
briancavalier authored
524 In other words, it's much like:
4af946a @briancavalier Docs for promise.yield
briancavalier authored
525
526 ```js
1866056 @skiadas Clarify the behavior of promise.yield. Fixes #164
skiadas authored
527 originalPromise.then(function() {
4af946a @briancavalier Docs for promise.yield
briancavalier authored
528 return promiseOrValue;
529 });
530 ```
f9dae39 @briancavalier API doc update
briancavalier authored
531
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
532 ### See also:
533 * [promise.else](#promiseelse) - return a default value when promise rejects
534
535 ## promise.else
536
537 **ALIAS:** `orElse()` for non-ES5 environments
538
539 ```js
07f8db6 @levibuzolic Fix minor "Async" typo in API docs
levibuzolic authored
540 var p1 = doAsyncOperationThatMightFail();
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
541 return p1.else(defaultValue);
542 ```
543
544 If a promise is rejected, `else` catches the rejection and resolves the returned promise with a default value. This is a shortcut for manually `catch`ing a promise and returning a different value, as such:
545
546 ```js
07f8db6 @levibuzolic Fix minor "Async" typo in API docs
levibuzolic authored
547 var p1 = doAsyncOperationThatMightFail();
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
548 return p1.catch(function() {
549 return defaultValue;
550 });
551 ```
552
553 ### See also:
554 * [promise.catch](#promisecatch) - intercept a rejected promise
555 * [promise.tap](#promisetap) - execute a side effect in a promise chain
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
556 * [promise.yield](#promiseyield) - execute a side effect in a promise chain
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
557
558 ## promise.tap
56281df @briancavalier Fix #181. Add promise.tap, unit tests, and docs
briancavalier authored
559
560 ```js
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
561 var promise2 = promise1.tap(onFulfilledSideEffect);
56281df @briancavalier Fix #181. Add promise.tap, unit tests, and docs
briancavalier authored
562 ```
563
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
564 Executes a function as a side effect when `promise` fulfills. Returns a new promise:
56281df @briancavalier Fix #181. Add promise.tap, unit tests, and docs
briancavalier authored
565
566 1. If `promise` fulfills, `onFulfilledSideEffect` is executed:
567 - If `onFulfilledSideEffect` returns successfully, the promise returned by `tap` fulfills with `promise`'s original fulfillment value. That is, `onfulfilledSideEffect`'s result is discarded.
568 - If `onFulfilledSideEffect` throws or returns a rejected promise, the promise returned by `tap` rejects with the same reason.
569 2. If `promise` rejects, `onFulfilledSideEffect` is *not* executed, and the promise returned by `tap` rejects with `promise`'s rejection reason.
570
571 These are equivalent:
572
573 ```js
574 // Using only .then()
575 promise.then(function(x) {
576 doSideEffectsHere(x);
577 return x;
578 });
579
580 // Using .tap()
581 promise.tap(doSideEffectsHere);
582 ```
583
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
584 ### See also:
585 * [promise.catch](#promisecatch) - intercept a rejected promise
586 * [promise.else](#promiseelse) - return a default value when promise rejects
587
588 ## promise.delay
67673f7 @briancavalier Docs for promise.apply
briancavalier authored
589
590 ```js
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
591 var delayedPromise = promise.delay(milliseconds);
67673f7 @briancavalier Docs for promise.apply
briancavalier authored
592 ```
593
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
594 Create a new promise that will, after `milliseconds` delay, fulfill with the same value as `promise`. If `promise` rejects, `delayedPromise` will be rejected immediately.
67673f7 @briancavalier Docs for promise.apply
briancavalier authored
595
596 ```js
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
597 var delayed;
598
599 // delayed is a pending promise that will become fulfilled
600 // in 1 second with the value "hello"
601 delayed = when('hello').delay(1000);
602
603 // delayed is a pending promise that will become fulfilled
604 // 1 second after anotherPromise resolves, or will become rejected
605 // *immediately* after anotherPromise rejects.
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
606 delayed = promise.delay(1000);
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
607
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
608 // Do something 1 second after promise resolves
609 promise.delay(1000).then(doSomething).catch(handleRejection);
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
610 ```
67673f7 @briancavalier Docs for promise.apply
briancavalier authored
611
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
612 ### See also:
613 * [promise.timeout](#promisetimeout)
614
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
615 ## promise.timeout
616
617 ```js
15b0ef7 @scothis Allow custom rejection reason for promise.timeout()
scothis authored
618 var timedPromise = promise.timeout(milliseconds, reason);
67673f7 @briancavalier Docs for promise.apply
briancavalier authored
619 ```
620
b40cb67 @briancavalier Update promise.timeout docs, add TimeoutError docs
briancavalier authored
621 Create a new promise that will reject with a [`TimeoutError`](#timeouterror) or a custom `reason` after a timeout if `promise` does not fulfill or reject beforehand.
15b0ef7 @scothis Allow custom rejection reason for promise.timeout()
scothis authored
622
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
623 ```js
624 var node = require('when/node');
625
626 // Lift fs.readFile so it returns promises
627 var readFile = node.lift(fs.readFile);
628
629 // Try to read the file, but timeout if it takes too long
630 function readWithTimeout(path) {
631 return readFile(path).timeout(500);
632 }
633 ```
634
b40cb67 @briancavalier Update promise.timeout docs, add TimeoutError docs
briancavalier authored
635 You can [pattern-match using `catch`](#promisecatch) to specifically handle `TimeoutError`s:
636
637 ```js
638 var when = require('when');
639
640 var p = readWithTimeout('/etc/passwd')
641 .catch(when.TimeoutError, handleTimeout) // handle only TimeoutError
642 .catch(handleFailure) // handle other errors
643 ```
644
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
645 ### See also:
646 * [promise.delay](#promisedelay)
647
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
648 ## promise.inspect
ffd54ae @briancavalier Add docs for promise.inspect
briancavalier authored
649
650 ```js
651 var status = promise.inspect();
652 ```
653
654 Returns a snapshot descriptor of the current state of `promise`. This descriptor is *not live* and will not update when `promise`'s state changes. The descriptor is an object with the following properties. When promise is:
655
656 * pending: `{ state: 'pending' }`
657 * fulfilled: `{ state: 'fulfilled', value: <promise's fulfillment value> }`
658 * rejected: `{ state: 'rejected', reason: <promise's rejection reason> }`
659
660 While there are use cases where synchronously inspecting a promise's state can be helpful, the use of `inspect` is discouraged. It is almost always preferable to simply use `when()` or `promise.then` to be notified when the promise fulfills or rejects.
661
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
662 ### See also:
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
663 * [when.settle](#whensettle) - settling an Array of promises
ffd54ae @briancavalier Add docs for promise.inspect
briancavalier authored
664
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
665 ## promise.with
9e29a66 @briancavalier Close #103. Implement promise.ensure, deprecate promise.always. API docs...
briancavalier authored
666
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
667 **ALIAS:** `withThis()` for non-ES5 environments
9e29a66 @briancavalier Close #103. Implement promise.ensure, deprecate promise.always. API docs...
briancavalier authored
668
669 ```js
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
670 var boundPromise = promise.with(object);
9e29a66 @briancavalier Close #103. Implement promise.ensure, deprecate promise.always. API docs...
briancavalier authored
671 ```
672
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
673 Creates a new promise that follows `promise`, but which will invoke its handlers with their `this` set to `object`. Normally, promise handlers are invoked with no specific `thisArg`, so `with` can be very useful when bridging promises to object-oriented patterns and libraries.
9e29a66 @briancavalier Close #103. Implement promise.ensure, deprecate promise.always. API docs...
briancavalier authored
674
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
675 **NOTE:** Promises returned from `with`/`withThis` are NOT Promises/A+ compliant, specifically violating 2.2.5 (http://promisesaplus.com/#point-41)
e769035 @jenius add docs for promise.else, close #243
jenius authored
676
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
677 For example:
e769035 @jenius add docs for promise.else, close #243
jenius authored
678
679 ```js
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
680 function Thing(value, message) {
681 this.value = value;
682 this.message = message;
683 }
e769035 @jenius add docs for promise.else, close #243
jenius authored
684
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
685 Thing.prototype.doSomething = function(x) {
686 var promise = doAsyncStuff(x);
687 return promise.with(this) // Set thisArg to this thing instance
688 .then(this.addValue) // Works since addValue will have correct thisArg
689 .then(this.format); // all subsequent promises retain thisArg
690 };
e769035 @jenius add docs for promise.else, close #243
jenius authored
691
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
692 Thing.prototype.addValue = function(y) {
693 return this.value + y;
694 };
e769035 @jenius add docs for promise.else, close #243
jenius authored
695
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
696 Thing.prototype.format = function(result) {
697 return this.message + result;
698 };
e769035 @jenius add docs for promise.else, close #243
jenius authored
699
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
700 // Using it
701 var thing = new Thing(41, 'The answer is ');
a26071a @briancavalier Add info about experimental progress propagation
briancavalier authored
702
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
703 thing.doSomething(1)
704 .with(console) // Re-bind thisArg now to console
705 .then(console.log); // Logs 'The answer is 42'
706
707 ```
a26071a @briancavalier Add info about experimental progress propagation
briancavalier authored
708
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
709 All promises created from `boundPromise` will also be bound to the same thisArg until `with` is used to re-bind or *unbind* it. In the previous example, the promise returned from `thing.doSomething` still has its thisArg bound to `thing`. That may not be what you want, so you can *unbind* it just before returning:
a26071a @briancavalier Add info about experimental progress propagation
briancavalier authored
710
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
711 ```js
712 Thing.prototype.doSomething = function(x) {
713 var promise = doAsyncStuff(x);
714 return promise.with(this)
715 .then(this.addValue)
716 .then(this.format)
717 .with(); // Unbind thisArg
718 };
719 ```
a26071a @briancavalier Add info about experimental progress propagation
briancavalier authored
720
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
721 ## promise.progress
a26071a @briancavalier Add info about experimental progress propagation
briancavalier authored
722
da12855 @briancavalier Deprecate progress, provide example of refactoring w/promise.tap
briancavalier authored
723 **DEPRECATED** Progress events are deprecated. See [Refactoring progress](#refactoring-progress)
724
a26071a @briancavalier Add info about experimental progress propagation
briancavalier authored
725 ```js
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
726 promise.progress(onProgress);
727 ```
a26071a @briancavalier Add info about experimental progress propagation
briancavalier authored
728
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
729 Registers a handler for progress updates from `promise`. It is a shortcut for:
a26071a @briancavalier Add info about experimental progress propagation
briancavalier authored
730
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
731 ```js
732 promise.then(void 0, void 0, onProgress);
a26071a @briancavalier Add info about experimental progress propagation
briancavalier authored
733 ```
734
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
735 ### Notes on Progress events
736
737 Progress events are not specified in Promises/A+ and are optional in Promises/A. They have proven to be useful in practice, but unfortunately, they are also underspecified, and there is no current *de facto* or agreed-upon behavior in the promise implementor community.
a26071a @briancavalier Add info about experimental progress propagation
briancavalier authored
738
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
739 In when.js, progress events will be propagated through a promise chain:
a26071a @briancavalier Add info about experimental progress propagation
briancavalier authored
740
741 1. In the same way as resolution and rejection handlers, your progress handler *MUST* return a progress event to be propagated to the next link in the chain. If you return nothing, *undefined will be propagated*.
742 1. Also in the same way as resolutions and rejections, if you don't register a progress handler (e.g. `.then(handleResolve, handleReject /* no progress handler */)`), the update will be propagated through.
743 1. **This behavior will likely change in future releases:** If your progress handler throws an exception, the exception will be propagated to the next link in the chain. The best thing to do is to ensure your progress handlers do not throw exceptions.
744 1. **Known Issue:** If you allow an exception to propagate and there are no more progress handlers in the chain, the exception will be silently ignored. We're working on a solution to this.
745
746 This gives you the opportunity to *transform* progress events at each step in the chain so that they are meaningful to the next step. It also allows you to choose *not* to transform them, and simply let them propagate untransformed, by not registering a progress handler.
747
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
748 Here is an example:
a26071a @briancavalier Add info about experimental progress propagation
briancavalier authored
749
750 ```js
751 function myProgressHandler(update) {
752 logProgress(update);
753 // Return a transformed progress update that is
754 // useful for progress handlers of the next promise!
755 return update + 1;
756 }
757
758 function myOtherProgressHandler(update) {
759 logProgress(update);
760 }
761
762 var d = when.defer();
18859e8 @briancavalier Improve when() and .then() docs and include basic information about hand...
briancavalier authored
763 d.promise.then(undefined, undefined, myProgressHandler);
a26071a @briancavalier Add info about experimental progress propagation
briancavalier authored
764
765 var chainedPromise = d.promise.then(doStuff);
18859e8 @briancavalier Improve when() and .then() docs and include basic information about hand...
briancavalier authored
766 chainedPromise.then(undefined, undefined, myOtherProgressHandler);
a26071a @briancavalier Add info about experimental progress propagation
briancavalier authored
767
768 var update = 1;
63c1683 @briancavalier Close #106. Add deprecation notice for progress(), prefer notify()
briancavalier authored
769 d.notify(update);
a26071a @briancavalier Add info about experimental progress propagation
briancavalier authored
770
771 // Results in:
772 // logProgress(1);
773 // logProgress(2);
774 ```
775
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
776 # Arrays
8d43875 @briancavalier Moving api docs to straight markdown file in docs dir. Trimming down an...
briancavalier authored
777
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
778 ## when.all
8d43875 @briancavalier Moving api docs to straight markdown file in docs dir. Trimming down an...
briancavalier authored
779
c7b882a @briancavalier Added when/timeout and when/delay
briancavalier authored
780 ```js
474ea1b @briancavalier Remove when.chain docs. Minor tweaks. Discourage use of callback args in...
briancavalier authored
781 var promise = when.all(array)
8d43875 @briancavalier Moving api docs to straight markdown file in docs dir. Trimming down an...
briancavalier authored
782 ```
783
a035e59 @briancavalier Added docs for when.join, plus more docs cleanup
briancavalier authored
784 Where:
785
786 * array is an Array *or a promise for an array*, which may contain promises and/or values.
787
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
788 Return a promise that will resolve only once all the items in `array` have resolved. The resolution value of the returned promise will be an array containing the resolution values of each of the items in `array`.
8d43875 @briancavalier Moving api docs to straight markdown file in docs dir. Trimming down an...
briancavalier authored
789
ccee2f3 @unscriptable update doc sections with some introductory text and add a few examples
unscriptable authored
790 If any of the promises is rejected, the returned promise will be rejected with the rejection reason of the first promise that was rejected.
791
a035e59 @briancavalier Added docs for when.join, plus more docs cleanup
briancavalier authored
792 ### See also:
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
793 * [when.join](#whenjoin)
794 * [when.settle](#whensettle)
a035e59 @briancavalier Added docs for when.join, plus more docs cleanup
briancavalier authored
795
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
796 ## when.map
a035e59 @briancavalier Added docs for when.join, plus more docs cleanup
briancavalier authored
797
798 ```js
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
799 var promise = when.map(array, mapper)
a035e59 @briancavalier Added docs for when.join, plus more docs cleanup
briancavalier authored
800 ```
801
802 Where:
8d43875 @briancavalier Moving api docs to straight markdown file in docs dir. Trimming down an...
briancavalier authored
803
889d8d2 @briancavalier Add when.filter. Pass array indices in when.map and when.filter, keys
briancavalier authored
804 * array is an Array or promise for an Array, which may contain promises and/or values
8d43875 @briancavalier Moving api docs to straight markdown file in docs dir. Trimming down an...
briancavalier authored
805
4606d47 @briancavalier Add when.settle docs
briancavalier authored
806 Traditional array map function, similar to `Array.prototype.map()`, but allows input to contain promises and/or values, and mapFunc may return either a value or a promise.
8d43875 @briancavalier Moving api docs to straight markdown file in docs dir. Trimming down an...
briancavalier authored
807
ccee2f3 @unscriptable update doc sections with some introductory text and add a few examples
unscriptable authored
808 If any of the promises is rejected, the returned promise will be rejected with the rejection reason of the first promise that was rejected.
809
8d43875 @briancavalier Moving api docs to straight markdown file in docs dir. Trimming down an...
briancavalier authored
810 The map function should have the signature:
811
c7b882a @briancavalier Added when/timeout and when/delay
briancavalier authored
812 ```js
889d8d2 @briancavalier Add when.filter. Pass array indices in when.map and when.filter, keys
briancavalier authored
813 mapFunc(value:*, index:Number):*
814 ```
815
816 Where:
817
818 * `value` fulfilled value
819 * `index` array index of `value`
820
821 ## when.filter
822
823 ```js
824 var promise = when.filter(array, predicate);
825 ```
826
827 Where:
828
829 * array is an Array or promise for an Array, which may contain promises and/or values
830
831 Filters the input array, returning a promise for the filtered array. The filtering `predicate` may return a boolean or promise for boolean.
832
833 If any of the promises is rejected, the returned promise will be rejected with the rejection reason of the first promise that was rejected.
834
835 The predicate should have the signature:
836
837 ```js
838 predicate(value:*, index:Number):boolean
8d43875 @briancavalier Moving api docs to straight markdown file in docs dir. Trimming down an...
briancavalier authored
839 ```
840
841 Where:
842
889d8d2 @briancavalier Add when.filter. Pass array indices in when.map and when.filter, keys
briancavalier authored
843 * `value` fulfilled value
844 * `index` array index of `value`
8d43875 @briancavalier Moving api docs to straight markdown file in docs dir. Trimming down an...
briancavalier authored
845
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
846 ## when.reduce
847 ## when.reduceRight
8d43875 @briancavalier Moving api docs to straight markdown file in docs dir. Trimming down an...
briancavalier authored
848
c7b882a @briancavalier Added when/timeout and when/delay
briancavalier authored
849 ```js
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
850 var promise = when.reduce(array, reducer [, initialValue])
851 var promise = when.reduceRight(array, reducer [, initialValue])
8d43875 @briancavalier Moving api docs to straight markdown file in docs dir. Trimming down an...
briancavalier authored
852 ```
853
168338c @briancavalier See #60. Docs for any/some() competitive races
briancavalier authored
854 Where:
855
856 * array is an Array *or a promise for an array*, which may contain promises and/or values.
857
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
858 Traditional array reduce function, similar to `Array.prototype.reduce()` and `Array.prototype.reduceRight()`, but input may contain promises and/or values, and reduceFunc may return either a value or a promise, *and* initialValue may be a promise for the starting value.
8d43875 @briancavalier Moving api docs to straight markdown file in docs dir. Trimming down an...
briancavalier authored
859
860 The reduce function should have the signature:
861
c7b882a @briancavalier Added when/timeout and when/delay
briancavalier authored
862 ```js
889d8d2 @briancavalier Add when.filter. Pass array indices in when.map and when.filter, keys
briancavalier authored
863 reducer(currentResult, value, index)
8d43875 @briancavalier Moving api docs to straight markdown file in docs dir. Trimming down an...
briancavalier authored
864 ```
865
866 Where:
867
bb8970e @briancavalier Add docs and JSDoc
briancavalier authored
868 * `currentResult` is the current accumulated reduce value
869 * `value` is the fully resolved value at `index` in `array`
870 * `index` is the *basis* of `value` ... practically speaking, this is the array index of the array corresponding to `value`
8d43875 @briancavalier Moving api docs to straight markdown file in docs dir. Trimming down an...
briancavalier authored
871
ccee2f3 @unscriptable update doc sections with some introductory text and add a few examples
unscriptable authored
872 ```js
873 // sum the eventual values of several promises
874 var sumPromise = when.reduce(inputPromisesOrValues, function (sum, value) {
875 return sum += value;
876 }, 0);
877 ```
878
879 If any of the promises is rejected, the returned promise will be rejected with the rejection reason of the first promise that was rejected.
880
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
881 ## when.settle
4606d47 @briancavalier Add when.settle docs
briancavalier authored
882
883 ```js
884 var promise = when.settle(array);
885 ```
886
cdc1df1 @briancavalier Add initial docs for when/guard. See #116
briancavalier authored
887 Returns a promise for an array containing the same number of elements as the input array. Each element is a descriptor object describing of the outcome of the corresponding element in the input. The returned promise will only reject if `array` itself is a rejected promise. Otherwise, it will always fulfill with an array of descriptors. This is in contrast to [when.all](#whenall), which will reject if any element of `array` rejects.
4606d47 @briancavalier Add when.settle docs
briancavalier authored
888
889 If the corresponding input promise is:
890
891 * fulfilled, the descriptor will be: `{ state: 'fulfilled', value: <fulfillmentValue> }`
436b18b @briancavalier Fix rejected descriptor reason
briancavalier authored
892 * rejected, the descriptor will be: `{ state: 'rejected', reason: <rejectionReason> }`
4606d47 @briancavalier Add when.settle docs
briancavalier authored
893
894 ```js
895 // Process all successful results, and also log all errors
896
897 // Input array
29abd5f @briancavalier Add promise.fold to TOC, minor cleanup
briancavalier authored
898 var array = [when.reject(1), 2, when(3), when.reject(4)];
4606d47 @briancavalier Add when.settle docs
briancavalier authored
899
900 // Settle all inputs
901 var settled = when.settle(array);
902
903 // Logs 1 & 4 and processes 2 & 3
904 settled.then(function(descriptors) {
905 descriptors.forEach(function(d) {
906 if(d.state === 'rejected') {
907 logError(d.reason);
908 } else {
909 processSuccessfulResult(d.value);
910 }
911 });
912 });
913 ```
914
915 ### See also:
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
916 * [when.all](#whenall)
917 * [promise.inspect](#inspect)
4606d47 @briancavalier Add when.settle docs
briancavalier authored
918
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
919 # Objects
bb8970e @briancavalier Add docs and JSDoc
briancavalier authored
920
32f98b4 @briancavalier Remove docs for keys.reduce()
briancavalier authored
921 the `when/keys` module provides `all()`, and `map()` for working with object keys, for the times when organizing promises in a hash using object keys is more convenient than using an array.
922
bb8970e @briancavalier Add docs and JSDoc
briancavalier authored
923 ## when/keys all
924
925 ```js
926 var promise = keys.all(object)
927 ```
928
929 Where:
930
931 * object is an Object *or a promise for an Object*, whose keys represent promises and/or values.
932
933 Return a promise that will resolve only once *all* the items in `object` have resolved. The resolution value of the returned promise will be an object containing the resolved key-value pairs of each of the items in `object`.
934
935 If any of the promises is rejected, the returned promise will be rejected with the rejection reason of the first promise that was rejected.
936
937 ### See also:
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
938 * [when.all](#whenall)
bb8970e @briancavalier Add docs and JSDoc
briancavalier authored
939
940 ## when/keys map
941
942 ```js
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
943 var promise = keys.map(object, mapper)
bb8970e @briancavalier Add docs and JSDoc
briancavalier authored
944 ```
945
946 Where:
947
948 * object is an Object *or a promise for an Object*, whose keys represent promises and/or values.
949
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
950 Similar to `when.map`, but for object keys, returns a promise for the key-mappedValue pairs by applying `mapper` to every value. `mapper` may return either a promise or a value.
bb8970e @briancavalier Add docs and JSDoc
briancavalier authored
951
952 If any of the promises is rejected, the returned promise will be rejected with the rejection reason of the first promise that was rejected.
953
954 The map function should have the signature:
955
956 ```js
889d8d2 @briancavalier Add when.filter. Pass array indices in when.map and when.filter, keys
briancavalier authored
957 mapFunc(value:*, key:String):*
bb8970e @briancavalier Add docs and JSDoc
briancavalier authored
958 ```
959
960 Where:
961
889d8d2 @briancavalier Add when.filter. Pass array indices in when.map and when.filter, keys
briancavalier authored
962 * `value` fulfilled value
963 * `key` key corresponding to `value`
bb8970e @briancavalier Add docs and JSDoc
briancavalier authored
964
965 ### See also:
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
966 * [when.map](#whenmap)
bb8970e @briancavalier Add docs and JSDoc
briancavalier authored
967
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
968 # Array Races
168338c @briancavalier See #60. Docs for any/some() competitive races
briancavalier authored
969
ccee2f3 @unscriptable update doc sections with some introductory text and add a few examples
unscriptable authored
970 The *competitive race* pattern may be used if one or more of the entire possible set of *eventual outcomes* are sufficient to resolve a promise.
971
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
972 ## when.any
168338c @briancavalier See #60. Docs for any/some() competitive races
briancavalier authored
973
974 ```js
474ea1b @briancavalier Remove when.chain docs. Minor tweaks. Discourage use of callback args in...
briancavalier authored
975 var promise = when.any(array)
168338c @briancavalier See #60. Docs for any/some() competitive races
briancavalier authored
976 ```
977
b87c726 @briancavalier Promote race to when.race public API. Add docs
briancavalier authored
978 A competitive race that allows one winner. The returned promise will:
168338c @briancavalier See #60. Docs for any/some() competitive races
briancavalier authored
979
f9657ec @briancavalier Update any/some/race docs based on suggestions from @kfranqueiro. Thanks...
briancavalier authored
980 * fulfill as soon as any one of the input promises fulfills, with the value of the fulfilled input promise, *or*
aa8a86a @briancavalier Make some/any reject if race is unwinnable due to too few inputs
briancavalier authored
981 * reject:
982 * with a `RangeError` if the input array is empty--i.e. it is impossible to have one winner.
983 * with an array of all the rejection reasons, if the input array is non-empty, and *all* input promises reject.
168338c @briancavalier See #60. Docs for any/some() competitive races
briancavalier authored
984
b87c726 @briancavalier Promote race to when.race public API. Add docs
briancavalier authored
985 ### See also:
986 * [when.race](#whenrace)
987 * [when.some](#whensome)
988
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
989 ## when.some
168338c @briancavalier See #60. Docs for any/some() competitive races
briancavalier authored
990
7064d56 @briancavalier Add deprecation notices to api docs for when.some and when/callbacks.pro...
briancavalier authored
991 **DEPRECATED**
992
168338c @briancavalier See #60. Docs for any/some() competitive races
briancavalier authored
993 ```js
1264d5f @briancavalier Revised docs for core, promise, arrays, object keys, and races
briancavalier authored
994 var promise = when.some(array, n)
168338c @briancavalier See #60. Docs for any/some() competitive races
briancavalier authored
995 ```
996
b87c726 @briancavalier Promote race to when.race public API. Add docs
briancavalier authored
997 A competitive race that requires `n` winners. The returned promise will
168338c @briancavalier See #60. Docs for any/some() competitive races
briancavalier authored
998
f9657ec @briancavalier Update any/some/race docs based on suggestions from @kfranqueiro. Thanks...
briancavalier authored
999 * fulfill when `n` promises are fulfilled with an array containing the values of the fulfilled input promises, *or*
aa8a86a @briancavalier Make some/any reject if race is unwinnable due to too few inputs
briancavalier authored
1000 * reject:
1001 * with a `RangeError` if the input contains fewer than `n` items--i.e. it is impossible to have `n` winners.
1002 * with an array containing the reasons of the rejected input promises when it becomes impossible for `n` promises to become fulfilled (ie when `(array.length - n) + 1` reject).
168338c @briancavalier See #60. Docs for any/some() competitive races
briancavalier authored
1003
ccee2f3 @unscriptable update doc sections with some introductory text and add a few examples
unscriptable authored
1004 ```js
f9657ec @briancavalier Update any/some/race docs based on suggestions from @kfranqueiro. Thanks...
briancavalier authored
1005 // ping all of the p2p servers and fail if at least two don't respond
1006 var remotes = [ping('p2p.cdn.com'), ping('p2p2.cdn.com'), ping('p2p3.cdn.com')];
1007 when.some(remotes, 2).done(itsAllOk, failGracefully);
ccee2f3 @unscriptable update doc sections with some introductory text and add a few examples
unscriptable authored
1008 ```
1009
b87c726 @briancavalier Promote race to when.race public API. Add docs
briancavalier authored
1010 ### See also:
1011 * [when.any](#whenany)
1012
1013 ## when.race
1014
1015 ```js
1016 var promise = when.race(array);
1017 ```
1018
1019 A competitive race to settle. The returned promise will settle in the same way as the earliest promise in `array` to settle. That is, it will
1020
1021 * fulfill if the earliest promise in array fulfills, with the same value, *or*
1022 * reject if the earliest promise in array rejects, with the same reason.
1023
1024 **WARNING:** As per the ES6 spec, the returned promise will *remain pending forever* if `array` is empty.
1025
1026 ### See also:
1027 * [when.any](#whenany)
1028
8bfe7ce @briancavalier Update verbage around iterate/unfold
briancavalier authored
1029 # Infinite Promise Sequences
9e349b1 @briancavalier Docs for when/poll. Started docs for unfold
briancavalier authored
1030
bb1585b @briancavalier Fix doc links, add doc changes to changelog
briancavalier authored
1031 [when.reduce](#whenreduce), [when/sequence](#whensequence), and [when/pipeline](#whenpipeline) are great ways to process asynchronous arrays of promises and tasks. Sometimes, however, you may not know the array in advance, or may not need or want to process *all* the items in the array. For example, here are a few situations where you may not know the bounds:
9e349b1 @briancavalier Docs for when/poll. Started docs for unfold
briancavalier authored
1032
1033 1. You need to process a queue to which items are still being added as you process it
c73e5ab @briancavalier Almost done with unfold docs
briancavalier authored
1034 1. You need to execute a task repeatedly until a particular condition becomes true
1035 1. You need to selectively process items in an array, rather than all items
9e349b1 @briancavalier Docs for when/poll. Started docs for unfold
briancavalier authored
1036
8bfe7ce @briancavalier Update verbage around iterate/unfold
briancavalier authored
1037 In these cases, you can use `when/iterate` and `when/unfold` to iteratively and asynchronously process items until a particular predicate is true, or even forever without blocking other code.
9e349b1 @briancavalier Docs for when/poll. Started docs for unfold
briancavalier authored
1038
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
1039 ## when.iterate
1040
0174a12 @briancavalier Add when/poll link to TOC. Reorder a bit
briancavalier authored
1041 ```js
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
1042 var promise = when.iterate(f, predicate, handler, seed);
0174a12 @briancavalier Add when/poll link to TOC. Reorder a bit
briancavalier authored
1043 ```
1044
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
1045 Generates a potentially infinite stream of promises by repeatedly calling `f` until `predicate` becomes true.
1046
1047 Where:
1048 * `f` - function that, given a seed, returns the next value or a promise for it.
c45bf53 @briancavalier Fix a few doc typos, thanks @unscriptable! Use tearDown for PromiseMoni...
briancavalier authored
1049 * `predicate` - function that receives the current iteration value, and should return truthy when the unfold should stop
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
1050 * `handler` - function that receives each value as it is produced by `f`. It may return a promise to delay the next iteration.
6d9d3e6 @briancavalier Clarify iterate handler receives seed first. See #353
briancavalier authored
1051 * `seed` - initial value provided to the handler, and first `f` invocation. May be a promise.
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
1052
1053 ### Examples
1054
1055 Here is a trivial example of counting up to any arbitrary number using promises and delays. Note that this "iteration" is asynchronous and will not block other code. It stores no intermediate arrays in memory, and will never blow the call stack.
1056
1057
1058 ```js
6d9d3e6 @briancavalier Clarify iterate handler receives seed first. See #353
briancavalier authored
1059 // Logs
1060 // 0
1061 // 1
1062 // 2
1063 // ...
1064 // 100000000000
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
1065 when.iterate(function(x) {
1066 return x+1;
1067 }, function(x) {
1068 // Stop when x >= 100000000000
1069 return x >= 100000000000;
1070 }, function(x) {
1071 console.log(x);
1072 }, 0).done();
1073 ```
1074
1075 Which becomes even nicer with [ES6 arrow functions](http://tc39wiki.calculist.org/es6/arrow-functions/):
1076
1077 ```js
1078 when.iterate(x => x+1, x => x >= 100000000000, x => console.log(x), 0).done();
1079 ```
4e1dc68 @briancavalier Start refactoring docs for 3.0
briancavalier authored
1080
1081 ## when.unfold
9e349b1 @briancavalier Docs for when/poll. Started docs for unfold
briancavalier authored
1082
1083 ```js
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
1084 var promise = when.unfold(unspool, predicate, handler, seed);
9e349b1 @briancavalier Docs for when/poll. Started docs for unfold
briancavalier authored
1085 ```
1086
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
1087 Similar to [`when/iterate`](#wheniterate), `when.unfold` generates a potentially infinite stream of promises by repeatedly calling `unspool` until `predicate` becomes true. `when.unfold` allows you to thread additional state information through the iteration.
0174a12 @briancavalier Add when/poll link to TOC. Reorder a bit
briancavalier authored
1088
c73e5ab @briancavalier Almost done with unfold docs
briancavalier authored
1089 Where:
1090 * `unspool` - function that, given a seed, returns a `[valueToSendToHandler, newSeed]` pair. May return an array, array of promises, promise for an array, or promise for an array of promises.
c45bf53 @briancavalier Fix a few doc typos, thanks @unscriptable! Use tearDown for PromiseMoni...
briancavalier authored
1091 * `predicate` - function that receives the current seed, and should return truthy when the unfold should stop
c73e5ab @briancavalier Almost done with unfold docs
briancavalier authored
1092 * `handler` - function that receives the `valueToSendToHandler` of the current iteration. This function can process `valueToSendToHandler` in whatever way you need. It may return a promise to delay the next iteration of the unfold.
41627f4 @briancavalier Fix comment about 2-step vertx check and RaveJS
briancavalier authored
1093 * `seed` - initial value provided to the first `unspool` invocation. May be a promise.
c73e5ab @briancavalier Almost done with unfold docs
briancavalier authored
1094
90ed0ab @briancavalier Add unfold example code
briancavalier authored
1095 ### Examples
1096
e01300b @briancavalier Finish unfold examples and text
briancavalier authored
1097 This example generates random numbers at random intervals for 10 seconds.
1098
c45bf53 @briancavalier Fix a few doc typos, thanks @unscriptable! Use tearDown for PromiseMoni...
briancavalier authored
1099 The `predicate` could easily be modified (to `return false;`) to generate random numbers *forever*. This would not overflow the call stack, and would not starve application code since it is asynchronous.
e01300b @briancavalier Finish unfold examples and text
briancavalier authored
1100
90ed0ab @briancavalier Add unfold example code
briancavalier authored
1101 ```js
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
1102 var when = require('when');
90ed0ab @briancavalier Add unfold example code
briancavalier authored
1103
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
1104 var end = Date.now() + 10000;
1105 var start = Date.now();
90ed0ab @briancavalier Add unfold example code
briancavalier authored
1106
1107 // Generate random numbers at random intervals!
1108 // Note that we could generate these forever, and never
1109 // blow the call stack, nor would we starve the application
1110 function unspool(seed) {
1111 // seed is passed in, although for this example, we don't need it
1112
1113 // Return a random number as the value, and the time it was generated
1114 // as the new seed
1115 var next = [Math.random(), Date.now()];
1116
1117 // Introduce a delay, just for fun, to show that we can return a promise
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
1118 return when(next).delay(Math.random() * 1000);
90ed0ab @briancavalier Add unfold example code
briancavalier authored
1119 }
1120
1121 // Stop after 10 seconds
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
1122 function predicate(time) {
1123 return time > end;
90ed0ab @briancavalier Add unfold example code
briancavalier authored
1124 }
1125
1126 function log(value) {
1127 console.log(value);
1128 }
1129
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
1130 when.unfold(unspool, predicate, log, start).then(function() {
90ed0ab @briancavalier Add unfold example code
briancavalier authored
1131 console.log('Ran for', Date.now() - start, 'ms');
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
1132 }).done();
1133 ```
1134
1135 Which again becomes quite compact with [ES6 arrow functions](http://tc39wiki.calculist.org/es6/arrow-functions/):
1136
1137 ```js
1138 when.unfold(unspool, time => time > end, x => console.log(x), start)
1139 .then(() => console.log('Ran for', Date.now() - start, 'ms'))
1140 .done();
90ed0ab @briancavalier Add unfold example code
briancavalier authored
1141 ```
1142
c45bf53 @briancavalier Fix a few doc typos, thanks @unscriptable! Use tearDown for PromiseMoni...
briancavalier authored
1143 This example iterates over files in a directory, mapping each file to the first line (or first 80 characters) of its content. It uses a `predicate` to terminate early, which would not be possible with `when.map`.
e01300b @briancavalier Finish unfold examples and text
briancavalier authored
1144
1145 Notice that, while the pair returned by `unspool` is an Array (not a promise), it does *contain* a promise as it's 0th element. The promise will be resolved by the `unfold` machinery.
1146
d23e41b @briancavalier Close #249. Move when/node/function to when/node. Add when/node/function...
briancavalier authored
1147 Notice also the use of `when/node`'s [`call()`](#node-style-asynchronous-functions) to call Node-style async functions (`fs.readdir` and `fs.readFile`), and return a promise instead of requiring a callback. This allows node-style functions can be promisified and composed with other promise-aware functions.
e01300b @briancavalier Finish unfold examples and text
briancavalier authored
1148
90ed0ab @briancavalier Add unfold example code
briancavalier authored
1149 ```js
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
1150 var when = require('when');
1151 var node = require('when/node');
90ed0ab @briancavalier Add unfold example code
briancavalier authored
1152
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
1153 var fs = node.liftAll(require('fs'));
1154
1155 // Lifted fs methods return promises
1156 var files = fs.readdir('.');
90ed0ab @briancavalier Add unfold example code
briancavalier authored
1157
1158 function unspool(files) {
1159 // Return the pair [<*promise* for contents of first file>, <remaining files>]
1160 // the first file's contents will be handed to printFirstLine()
1161 // the remaining files will be handed to condition(), and then
1162 // to the next call to unspool.
1163 // So we are iteratively working our way through the files in
1164 // the dir, but allowing condition() to stop the iteration at
1165 // any point.
1166 var file, content;
1167
1168 file = files[0];
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
1169 content = fs.readFile(file)
3c118cb @briancavalier Update docs with catch/finally aliases
briancavalier authored
1170 .catch(function(e) {
90ed0ab @briancavalier Add unfold example code
briancavalier authored
1171 return '[Skipping dir ' + file + ']';
1172 });
1173 return [content, files.slice(1)];
1174 }
1175
5e6a733 @briancavalier Merge master to dev
briancavalier authored
1176 function predicate(remaining) {
90ed0ab @briancavalier Add unfold example code
briancavalier authored
1177 // This could be any test we want. For fun, stop when
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
1178 // the next file name starts with a 'p'.
90ed0ab @briancavalier Add unfold example code
briancavalier authored
1179 return remaining[0].charAt(0) === 'p';
1180 }
1181
1182 function printFirstLine(content) {
1183 // Even though contents was a promise in unspool() above,
1184 // when/unfold ensures that it is fully resolved here, i.e. it is
1185 // not a promise any longer.
d23e41b @briancavalier Close #249. Move when/node/function to when/node. Add when/node/function...
briancavalier authored
1186 // We can do any work, even asynchronous work, we need
90ed0ab @briancavalier Add unfold example code
briancavalier authored
1187 // here on the current file
1188
1189 // Node fs returns buffers, convert to string
1190 content = String(content);
1191
1192 // Print the first line, or only the first 80 chars if the fist line is longer
1193 console.log(content.slice(0, Math.min(80, content.indexOf('\n'))));
1194 }
1195
5e6a733 @briancavalier Merge master to dev
briancavalier authored
1196 when.unfold(unspool, predicate, printFirstLine, files).done();
90ed0ab @briancavalier Add unfold example code
briancavalier authored
1197 ```
c73e5ab @briancavalier Almost done with unfold docs
briancavalier authored
1198
0174a12 @briancavalier Add when/poll link to TOC. Reorder a bit
briancavalier authored
1199 # Task Execution
dcbfb84 @briancavalier Adding sequence, pipeline, and parallel docs
briancavalier authored
1200
ff9412b @briancavalier Doc clarifications. Self-optimizing function for pipeline. Improved uni...
briancavalier authored
1201 These modules allow you to execute tasks in series or parallel. Each module takes an Array of task functions (or a *promise* for an Array), executes the tasks, and returns a promise that resolves when all the tasks have completed.
1202
dcbfb84 @briancavalier Adding sequence, pipeline, and parallel docs
briancavalier authored
1203 ## when/sequence
1204
1205 ```js
0174a12 @briancavalier Add when/poll link to TOC. Reorder a bit
briancavalier authored
1206 var sequence = require('when/sequence');
ff9412b @briancavalier Doc clarifications. Self-optimizing function for pipeline. Improved uni...
briancavalier authored
1207
0174a12 @briancavalier Add when/poll link to TOC. Reorder a bit
briancavalier authored
1208 var resultsPromise = sequence(arrayOfTasks, arg1, arg2 /*, ... */);
dcbfb84 @briancavalier Adding sequence, pipeline, and parallel docs
briancavalier authored
1209 ```
1210
1211 Run an array of tasks in sequence, without overlap. Each task will be called with the arguments passed to `when.sequence()`, and each may return a promise or a value.
1212
1213 When all tasks have completed, the returned promise will resolve to an array containing the result of each task at the corresponding array position. The returned promise will reject when any task throws or returns a rejection.
1214
1215 ## when/pipeline
1216
1217 ```js
0174a12 @briancavalier Add when/poll link to TOC. Reorder a bit
briancavalier authored
1218 var pipeline = require('when/pipeline');
ff9412b @briancavalier Doc clarifications. Self-optimizing function for pipeline. Improved uni...
briancavalier authored
1219
0174a12 @briancavalier Add when/poll link to TOC. Reorder a bit
briancavalier authored
1220 var resultsPromise = pipeline(arrayOfTasks, arg1, arg2 /*, ... */);
dcbfb84 @briancavalier Adding sequence, pipeline, and parallel docs
briancavalier authored
1221 ```
1222
1223 Run an array of tasks in sequence, without overlap, similarly to [when/sequence](#whensequence). The *first task* (e.g. `arrayOfTasks[0]`) will be called with the arguments passed to `when.pipeline()`, and each subsequence task will be called with the result of the previous task.
1224
1225 Again, each may return a promise or a value. When a task returns a promise, the fully resolved value will be passed to the next task.
1226
1227 When all tasks have completed, the returned promise will resolve to the result of the last task. The returned promise will reject when any task throws or returns a rejection.
1228
1229 ## when/parallel
1230
1231 ```js
0174a12 @briancavalier Add when/poll link to TOC. Reorder a bit
briancavalier authored
1232 var parallel = require('when/parallel');
ff9412b @briancavalier Doc clarifications. Self-optimizing function for pipeline. Improved uni...
briancavalier authored
1233
0174a12 @briancavalier Add when/poll link to TOC. Reorder a bit
briancavalier authored
1234 var resultsPromise = parallel(arrayOfTasks, arg1, arg2 /*, ... */);
dcbfb84 @briancavalier Adding sequence, pipeline, and parallel docs
briancavalier authored
1235 ```
1236
dbee625 @briancavalier Add info about calling resolve/reject multiple times.
briancavalier authored
1237 Run an array of tasks in "parallel". The tasks are allowed to execute in any order, and may interleave if they are asynchronous. Each task will be called with the arguments passed to `when.parallel()`, and each may return a promise or a value.
dcbfb84 @briancavalier Adding sequence, pipeline, and parallel docs
briancavalier authored
1238
1239 When all tasks have completed, the returned promise will resolve to an array containing the result of each task at the corresponding array position. The returned promise will reject when any task throws or returns a rejection.
1240
9e349b1 @briancavalier Docs for when/poll. Started docs for unfold
briancavalier authored
1241 ## when/poll
1242
1243 ```js
0174a12 @briancavalier Add when/poll link to TOC. Reorder a bit
briancavalier authored
1244 var poll = require('when/poll');
9e349b1 @briancavalier Docs for when/poll. Started docs for unfold
briancavalier authored
1245
0174a12 @briancavalier Add when/poll link to TOC. Reorder a bit
briancavalier authored
1246 var resultPromise = poll(task, interval, condition /*, initialDelay */);
9e349b1 @briancavalier Docs for when/poll. Started docs for unfold
briancavalier authored
1247 ```
1248
1249 Where:
1250
d0f6c3d @gdoron Update api.md
gdoron authored
1251 * `task` - function to be called periodically
1252 * `interval` - interval between calls to `task`. It may be a number *or* a function that returns a promise. If it's a function, the next polling iteration will wait until the promise fulfills.
1253 * `condition` - function that evaluates each result of `task`. Polling will continue until it returns a truthy value.
1254 * `initialDelay` - if provided and truthy, the first execution of `task` will be delayed by `interval`. If not provided, or falsey, the first execution of `task` will happen as soon as possible.
9e349b1 @briancavalier Docs for when/poll. Started docs for unfold
briancavalier authored
1255
d0f6c3d @gdoron Update api.md
gdoron authored
1256 Execute a task (`task`) repeatedly at the specified `interval`, until the `condition` function returns true. The `resultPromise` will be resolved with the most recent value returned from `task`. If `task` fails (throws an exception or returns a rejected promise) before `condition` returns true, the `resultPromise` will be rejected.
9e349b1 @briancavalier Docs for when/poll. Started docs for unfold
briancavalier authored
1257
1258 # Interacting with non-promise code
1c65160 @renato-zannon API docs for when/function
renato-zannon authored
1259
aad1685 @renato-zannon Incorporate @briancavalier's suggestions
renato-zannon authored
1260 These modules are aimed at dampening the friction between code that is based on promises and code that follows more conventional approaches to make asynchronous tasks and/or error handling. By using them, you are more likely to be able to reuse code that already exists, while still being able to reap the benefits of promises on your new code.
1c65160 @renato-zannon API docs for when/function
renato-zannon authored
1261
1262 ## Synchronous functions
1263
94391bc @briancavalier Close #126. Rename bind() to lift(), preserve deprecated bind() alias.
briancavalier authored
1264 The `when/function` module contains functions for calling and adapting "normal" functions (i.e. those that take plain values, return plain values, and throw exceptions on errors). By calling those functions with `fn.call` and `fn.apply`, or by creating a new function with `fn.lift`, the return value will always be a promise, and thrown exceptions will be turned into rejections. As a bonus, promises given as arguments will be transparently resolved before the call.
1c65160 @renato-zannon API docs for when/function
renato-zannon authored
1265
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
1266 ### fn.lift
88f7e6f @briancavalier Add liftAll docs. need examples
briancavalier authored
1267
1268 ```js
13b91c2 @briancavalier Update changelog and API docs for upcoming 3.2.0
briancavalier authored
1269 var promiseFunction = fn.lift(normalFunction);
1270
1271 // Deprecated: using lift to partially apply while lifting
88f7e6f @briancavalier Add liftAll docs. need examples
briancavalier authored
1272 var promiseFunction = fn.lift(normalFunction, arg1, arg2/* ...more args */);
1273 ```
1274
13b91c2 @briancavalier Update changelog and API docs for upcoming 3.2.0
briancavalier authored
1275 When the same function will be called through `fn.call()` or `fn.apply()` multiple times, it can be more efficient to lift it create a wrapper function that has promise-awareness and exposes the same behavior as the original function. That's what `fn.lift()` does: It takes a normal function and returns a new, promise-aware version of it.
1276
1277 Note: Use [`when.lift`](#whenlift) instead: `when.lift` is equivalent to, but also slightly faster than `fn.lift` when used without the (now deprecated) partial application feature.
88f7e6f @briancavalier Add liftAll docs. need examples
briancavalier authored
1278
1279 ```js
1dff5e1 @briancavalier Fix #274. Add missing TOC links, plus other minor api doc cleanup
briancavalier authored
1280 var when = require('when');
1281 var fn = require('when/function');
88f7e6f @briancavalier Add liftAll docs. need examples
briancavalier authored
1282
1283 function setText(element, text) {
1284 element.text = text;
1285 }
1286
1287 function getMessage() {
1288 // Async function that returns a promise
1289 }
1290
1291 var element = {};
1292
1293 // Resolving the promise ourselves
1294 getMessage().then(function(message) {
1295 setText(element, message);
1296 });
1297
1298 // Using fn.call()
1299 fn.call(setText, element, getMessage());
1300
1301 // Creating a lifted function using fn.lift()
1302 var promiseSetText = fn.lift(setText);
1303 promiseSetText(element, getMessage());
1304
1305 // Partial application
1306 var setElementMessage = fn.lift(setText, element);
1307 setElementMessage(getMessage());
1308 ```
1309
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
1310 ### fn.liftAll
88f7e6f @briancavalier Add liftAll docs. need examples
briancavalier authored
1311
1312 ```js
1313 var liftedApi = fn.liftAll(srcApi);
1314
1315 var liftedApi = fn.liftAll(srcApi, transform);
1316
1317 var destApi = fn.liftAll(srcApi, transform, destApi);
1318 ```
1319
1320 Lifts all the methods of a source object, returning a new object with all the lifted methods. The optional `transform` function allows you to rename or otherwise customize how the lifted functions are added to the returned object. If `destApi` is provided, lifted methods will be added to it, instead of to a new object, and `destApi` will be returned.
1321
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
1322 ### fn.call
1c65160 @renato-zannon API docs for when/function
renato-zannon authored
1323
aad1685 @renato-zannon Incorporate @briancavalier's suggestions
renato-zannon authored
1324 ```js
1325 var promisedResult = fn.call(normalFunction, arg1, arg2/* ...more args */);
1326 ```
1327
1c65160 @renato-zannon API docs for when/function
renato-zannon authored
1328 A parallel to the `Function.prototype.call` function, that gives promise-awareness to the function given as first argument.
1329
1330 ```js
1dff5e1 @briancavalier Fix #274. Add missing TOC links, plus other minor api doc cleanup
briancavalier authored
1331 var when = require('when');
1332 var fn = require('when/function');
1c65160 @renato-zannon API docs for when/function
renato-zannon authored
1333
1334 function divideNumbers(a, b) {
1335 if(b !== 0) {
1336 return a / b;
1337 } else {
1338 throw new Error("Can't divide by zero!");
1339 }
1340 }
1341
1342 // Prints '2'
1343 fn.call(divideNumbers, 10, 5).then(console.log);
1344
1345 // Prints '4'
29abd5f @briancavalier Add promise.fold to TOC, minor cleanup
briancavalier authored
1346 var promiseForFive = when(5);
1c65160 @renato-zannon API docs for when/function
renato-zannon authored
1347 fn.call(divideNumbers, 20, promiseForFive).then(console.log);
1348
1349 // Prints "Can't divide by zero!"
1350 fn.call(divideNumbers, 10, 0).then(console.log, console.error);
1351 ```
1352
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
1353 ### fn.apply
1c65160 @renato-zannon API docs for when/function
renato-zannon authored
1354
aad1685 @renato-zannon Incorporate @briancavalier's suggestions
renato-zannon authored
1355 ```js
1356 var promisedResult = fn.apply(normalFunction, [arg1, arg2/* ...more args */]);
1357 ```
1358
1c65160 @renato-zannon API docs for when/function
renato-zannon authored
1359 `fn.apply` is to [`fn.call`](#fncall) as `Function.prototype.apply` is to `Function.prototype.call`: what changes is the way the arguments are taken. While `fn.call` takes the arguments separately, `fn.apply` takes them as an array.
1360
1361 ```js
1dff5e1 @briancavalier Fix #274. Add missing TOC links, plus other minor api doc cleanup
briancavalier authored
1362 var when = require('when');
1363 var fn = require('when/function');
1c65160 @renato-zannon API docs for when/function
renato-zannon authored
1364
1365 function sumMultipleNumbers() {
1366 return Array.prototype.reduce.call(arguments, function(prev, n) {
1367 return prev + n;
1368 }, 0);
1369 }
1370
1371 // Prints '50'
1372 fn.apply(sumMultipleNumbers, [10, 20, 20]).then(console.log, console.error);
1373
1374 // Prints 'something wrong happened', and the sum function never executes
1375 var shortCircuit = when.reject("something wrong happened");
1376 fn.apply(sumMultipleNumbers, [10, 20, shortCircuit]).then(console.log, console.error);
1377 ```
1378
6558022 @briancavalier Update docs for when.iterate and unfold. Clean up formatting and "see al...
briancavalier authored
1379 ### fn.compose
94391bc @briancavalier Close #126. Rename bind() to lift(), preserve deprecated bind() alias.
briancavalier authored
1380
aad1685 @renato-zannon Incorporate @briancavalier's suggestions
renato-zannon authored
1381 ```js
88f7e6f @briancavalier Add liftAll docs. need examples
briancavalier authored
1382 var composedFunc = fn.compose(func1, func2 /* ...more functions */);
aad1685 @renato-zannon Incorporate @briancavalier's suggestions
renato-zannon authored
1383 ```
1384
88f7e6f @briancavalier Add liftAll docs. need examples
briancavalier authored
1385 Composes multiple functions by piping their return values. It is transparent to whether the functions return 'regular' values or promises: the piped argument is always a resolved value. If one of the functions throws or returns a rejected promise, the promise returned by `composedFunc` will be rejected.
1c65160 @renato-zannon API docs for when/function
renato-zannon authored
1386
1387 ```js
88f7e6f @briancavalier Add liftAll docs. need examples
briancavalier authored
1388 // Reusing the same functions from the fn.lift() example
1c65160 @renato-zannon API docs for when/function
renato-zannon authored
1389
88f7e6f @briancavalier Add liftAll docs. need examples
briancavalier authored
1390 // Gets the message from the server every 1s, then sets it on the 'element'
1391 var refreshMessage = fn.compose(getMessage, setElementMessage);
1392 setInterval(refreshMessage, 1000);
1c65160 @renato-zannon API docs for when/function
renato-zannon authored
1393
88f7e6f @briancavalier Add liftAll docs. need examples
briancavalier authored
1394 // Which is equivalent to:
1395 setInterval(function() {
1396 return fn.call(getMessage).then(setElementMessage);
1397 }, 1000);
1398 ```
1c65160 @renato-zannon API docs for when/function
renato-zannon authored
1399
0174a12 @briancavalier Add when/poll link to TOC. Reorder a bit
briancavalier authored
1400 # Node-style asynchronous functions
0e125d6 @renato-zannon API docs for node/function
renato-zannon authored
1401
d23e41b @briancavalier Close #249. Move when/node/function to when/node. Add when/node/function...
briancavalier authored
1402 Node.js APIs have their own standard for asynchronous functions: Instead of taking an errback, errors are passed as the first argument to the callback function. To use promises instead of callbacks with node-style asynchronous functions, you can use the `when/node` module, which is very similar to `when/callbacks`, but tuned to this convention.
0e125d6 @renato-zannon API docs for node/function
renato-zannon authored
1403
13b91c2 @briancavalier Update changelog and API docs for upcoming 3.2.0
briancavalier authored
1404 Note: There are some Node.js functions that don't follow the typical Node-style async function conventions, such as `http.get`. These functions will not work with `when/node`.
0f9b031 @gotdibbs Clarified usage of node-style function wrappers
gotdibbs authored
1405
0174a12 @briancavalier Add when/poll link to TOC. Reorder a bit
briancavalier authored
1406 ## node.lift
88f7e6f @briancavalier Add liftAll docs. need examples
briancavalier authored
1407
1408 ```js
13b91c2 @briancavalier Update changelog and API docs for upcoming 3.2.0
briancavalier authored
1409 var promiseFunc = nodefn.lift(nodeStyleFunction);
1410
1411 // Deprecated: using lift to partially apply while lifting
88f7e6f @briancavalier Add liftAll docs. need examples
briancavalier authored
1412 var promiseFunc = nodefn.lift(nodeStyleFunction, arg1, arg2/*...more args*/);
1413 ```
1414
1415 Function based on the same principles from [`fn.lift()`](#fnlift) and [`callbacks.lift()`](#callbackslift), but tuned to handle nodejs-style async functions.
1416
1417 ```js
1dff5e1 @briancavalier Fix #274. Add missing TOC links, plus other minor api doc cleanup
briancavalier authored
1418 var dns = require('dns');
1419 var when = require('when');
1420 var nodefn = require('when/node');
88f7e6f @briancavalier Add liftAll docs. need examples
briancavalier authored
1421
1422 var resolveAddress = nodefn.lift(dns.resolve);
1423
1424 when.join(
1dff5e1 @briancavalier Fix #274. Add missing TOC links, plus other minor api doc cleanup
briancavalier authored
1425 resolveAddress('twitter.com'),
1426 resolveAddress('facebook.com'),
1427 resolveAddress('google.com')
88f7e6f @briancavalier Add liftAll docs. need examples
briancavalier authored
1428 ).then(function(addresses) {
1429 // All addresses resolved
1430 }).catch(function(reason) {
1431 // At least one of the lookups failed
1432 });
1433 ```
1434
0174a12 @briancavalier Add when/poll link to TOC. Reorder a bit
briancavalier authored
1435 ## node.liftAll
88f7e6f @briancavalier Add liftAll docs. need examples
briancavalier authored
1436
1437 ```js
1438 var liftedApi = fn.liftAll(srcApi);
1439
1440 var liftedApi = fn.liftAll(srcApi, transform);
1441
1442 var destApi = fn.liftAll(srcApi, transform, destApi);
1443 ```
1444
1445 Lifts all the methods of a source object, returning a new object with all the lifted methods. The optional `transform` function allows you to rename or otherwise customize how the lifted functions are added to the returned object. If `destApi` is provided, lifted methods will be added to it, instead of to a new object, and `destApi` will be returned.
1446
1447 ```js
1448 // Lift the entire dns API
456685b @briancavalier Add more liftAll examples
briancavalier authored
1449 var dns = require('dns');
1450 var promisedDns = node.liftAll(dns);
88f7e6f @briancavalier Add liftAll docs. need examples
briancavalier authored
1451
1452 when.join(
456685b @briancavalier Add more liftAll examples
briancavalier authored
1453 promisedDns.resolve("twitter.com"),
1454 promisedDns.resolveNs("facebook.com"),
1455 promisedDns.resolveMx("google.com")
88f7e6f @briancavalier Add liftAll docs. need examples
briancavalier authored
1456 ).then(function(addresses) {
1457 // All addresses resolved
1458 }).catch(function(reason) {
1459 // At least one of the lookups failed
1460 });
1461 ```
1462
456685b @briancavalier Add more liftAll examples
briancavalier authored
1463 For additional flexibility, you can use the optional `transform` function to do things like renaming:
1464
1465 ```js
1466 // Lift all of the fs methods, but name them with an 'Async' suffix
1467 var fs = require('fs');
1468 var promisedFs = node.liftAll(fs, function(promisedFs, liftedFunc, name) {
1469 promisedFs[name + 'Async'] = liftedFunc;
1470 return promisedFs;
1471 });
1472
1473 promisedFs.readFileAsync('file.txt').done(console.log.bind(console));
1474 ```
1475
1476 You can also supply your own destination object onto which all of the lifted functions will be added:
1477
1478 ```js
1479 // Lift all of the fs methods, but name them with an 'Async' suffix
1480 // and add them back onto fs!
1481 var fs = require('fs');
1482 var promisedFs = node.liftAll(fs, function(promisedFs, liftedFunc, name) {
1483 promisedFs[name + 'Async'] = liftedFunc;
1484 return promisedFs;
1485 }, fs);
1486
1487 fs.readFileAsync('file.txt').done(console.log.bind(console));
1488 ```
1489
0174a12 @briancavalier Add when/poll link to TOC. Reorder a bit
briancavalier authored
1490 ## node.call
0e125d6 @renato-zannon API docs for node/function
renato-zannon authored
1491
aad1685 @renato-zannon Incorporate @briancavalier's suggestions
renato-zannon authored
1492 ```js
1493 var promisedResult = nodefn.call(nodeStyleFunction, arg1, arg2/*...more args*/);
1494 ```
1495
6424a4d @renato-zannon Fix internal links
renato-zannon authored
1496 Analogous to [`fn.call()`](#fncall) and [`callbacks.call()`](#callbackscall): Takes a function plus optional arguments to that function, and returns a promise for its final value. The promise will be resolved or rejected depending on whether the conventional error argument is passed or not.
0e125d6 @renato-zannon API docs for node/function
renato-zannon authored
1497
1498 ```js
1dff5e1 @briancavalier Fix #274. Add missing TOC links, plus other minor api doc cleanup
briancavalier authored
1499 var fs = require('fs');
9d2c2d5 @Offirmo Update api.md
Offirmo authored
1500 var nodefn = require('when/node');
0e125d6 @renato-zannon API docs for node/function
renato-zannon authored
1501
1dff5e1 @briancavalier Fix #274. Add missing TOC links, plus other minor api doc cleanup
briancavalier authored
1502 var loadPasswd = nodefn.call(fs.readFile, '/etc/passwd');
0e125d6 @renato-zannon API docs for node/function
renato-zannon authored
1503
1dff5e1 @briancavalier Fix #274. Add missing TOC links, plus other minor api doc cleanup
briancavalier authored
1504 loadPasswd.done(function(passwd) {
1505 console.log('Contents of /etc/passwd:\n' + passwd);
0e125d6 @renato-zannon API docs for node/function
renato-zannon authored
1506 }, function(error) {
1dff5e1 @briancavalier Fix #274. Add missing TOC links, plus other minor api doc cleanup
briancavalier authored
1507 console.log('Something wrong happened: ' + error);
0e125d6 @renato-zannon API docs for node/function
renato-zannon authored
1508 });
1509 ```
1510
0174a12 @briancavalier Add when/poll link to TOC. Reorder a bit
briancavalier authored
1511 ## node.apply
0e125d6 @renato-zannon API docs for node/function
renato-zannon authored
1512
aad1685 @renato-zannon Incorporate @briancavalier's suggestions
renato-zannon authored
1513 ```js
5f548a6 @renato-zannon Typo
renato-zannon authored
1514 var promisedResult = nodefn.apply(nodeStyleFunction, [arg1, arg2/*...more args*/]);
aad1685 @renato-zannon Incorporate @briancavalier's suggestions
renato-zannon authored
1515 ```
1516
d23e41b @briancavalier Close #249. Move when/node/function to when/node. Add when/node/function...
briancavalier authored
1517 Following the tradition from `when/function` and `when/callbacks`, `when/node` also provides a array-based alternative to `nodefn.call()`.
0e125d6 @renato-zannon API docs for node/function
renato-zannon authored
1518
1519 ```js
1dff5e1 @briancavalier Fix #274. Add missing TOC links, plus other minor api doc cleanup
briancavalier authored
1520 var fs = require('fs');
1521 var nodefn = require('when/node');
0e125d6 @renato-zannon API docs for node/function
renato-zannon authored
1522
1dff5e1 @briancavalier Fix #274. Add missing TOC links, plus other minor api doc cleanup
briancavalier authored
1523 var loadPasswd = nodefn.apply(fs.readFile, ['/etc/passwd']);
0e125d6 @renato-zannon API docs for node/function
renato-zannon authored
1524
1dff5e1 @briancavalier Fix #274. Add missing TOC links, plus other minor api doc cleanup
briancavalier authored
1525 loadPasswd.done(function(passwd) {
1526 console.log('Contents of /etc/passwd:\n' + passwd);
0f9b031 @gotdibbs Clarified usage of node-style function wrappers
gotdibbs authored
1527 }, function(error) {
1dff5e1 @briancavalier Fix #274. Add missing TOC links, plus other minor api doc cleanup
briancavalier authored
1528 console.log('Something wrong happened: ' + error);
0e125d6 @renato-zannon API docs for node/function
renato-zannon authored
1529 });
1530 ```
1531
0174a12 @briancavalier Add when/poll link to TOC. Reorder a bit
briancavalier authored