1 | <a href="https://promisesaplus.com/"><img src="https://promisesaplus.com/assets/logo-small.png" align="right" /></a>
|
2 | # promise
|
3 |
|
4 | This is a simple implementation of Promises. It is a super set of ES6 Promises designed to have readable, performant code and to provide just the extensions that are absolutely necessary for using promises today.
|
5 |
|
6 | For detailed tutorials on its use, see www.promisejs.org
|
7 |
|
8 | **N.B.** This promise exposes internals via underscore (`_`) prefixed properties. If you use these, your code will break with each new release.
|
9 |
|
10 | [![travis][travis-image]][travis-url]
|
11 | [![dep][dep-image]][dep-url]
|
12 | [![npm][npm-image]][npm-url]
|
13 | [![downloads][downloads-image]][downloads-url]
|
14 |
|
15 | [travis-image]: https://img.shields.io/travis/then/promise.svg?style=flat
|
16 | [travis-url]: https://travis-ci.org/then/promise
|
17 | [dep-image]: https://img.shields.io/david/then/promise.svg?style=flat
|
18 | [dep-url]: https://david-dm.org/then/promise
|
19 | [npm-image]: https://img.shields.io/npm/v/promise.svg?style=flat
|
20 | [npm-url]: https://npmjs.org/package/promise
|
21 | [downloads-image]: https://img.shields.io/npm/dm/promise.svg?style=flat
|
22 | [downloads-url]: https://npmjs.org/package/promise
|
23 |
|
24 | ## Installation
|
25 |
|
26 | **Server:**
|
27 |
|
28 | $ npm install promise
|
29 |
|
30 | **Client:**
|
31 |
|
32 | You can use browserify on the client, or use the pre-compiled script that acts as a polyfill.
|
33 |
|
34 | ```html
|
35 | <script src="https://www.promisejs.org/polyfills/promise-6.1.0.js"></script>
|
36 | ```
|
37 |
|
38 | Note that the [es5-shim](https://github.com/es-shims/es5-shim) must be loaded before this library to support browsers pre IE9.
|
39 |
|
40 | ```html
|
41 | <script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/3.4.0/es5-shim.min.js"></script>
|
42 | ```
|
43 |
|
44 | ## Usage
|
45 |
|
46 | The example below shows how you can load the promise library (in a way that works on both client and server using node or browserify). It then demonstrates creating a promise from scratch. You simply call `new Promise(fn)`. There is a complete specification for what is returned by this method in [Promises/A+](http://promises-aplus.github.com/promises-spec/).
|
47 |
|
48 | ```javascript
|
49 | var Promise = require('promise');
|
50 |
|
51 | var promise = new Promise(function (resolve, reject) {
|
52 | get('http://www.google.com', function (err, res) {
|
53 | if (err) reject(err);
|
54 | else resolve(res);
|
55 | });
|
56 | });
|
57 | ```
|
58 |
|
59 | If you need [domains](https://nodejs.org/api/domain.html) support, you should instead use:
|
60 |
|
61 | ```js
|
62 | var Promise = require('promise/domains');
|
63 | ```
|
64 |
|
65 | If you are in an environment that implements `setImmediate` and don't want the optimisations provided by asap, you can use:
|
66 |
|
67 | ```js
|
68 | var Promise = require('promise/setimmediate');
|
69 | ```
|
70 |
|
71 | If you only want part of the features, e.g. just a pure ES6 polyfill:
|
72 |
|
73 | ```js
|
74 | var Promise = require('promise/lib/es6-extensions');
|
75 | // or require('promise/domains/es6-extensions');
|
76 | // or require('promise/setimmediate/es6-extensions');
|
77 | ```
|
78 |
|
79 | ## Unhandled Rejections
|
80 |
|
81 | By default, promises silence any unhandled rejections.
|
82 |
|
83 | You can enable logging of unhandled ReferenceErrors and TypeErrors via:
|
84 |
|
85 | ```js
|
86 | require('promise/lib/rejection-tracking').enable();
|
87 | ```
|
88 |
|
89 | Due to the performance cost, you should only do this during development.
|
90 |
|
91 | You can enable logging of all unhandled rejections if you need to debug an exception you think is being swallowed by promises:
|
92 |
|
93 | ```js
|
94 | require('promise/lib/rejection-tracking').enable(
|
95 | {allRejections: true}
|
96 | );
|
97 | ```
|
98 |
|
99 | Due to the high probability of false positives, I only recommend using this when debugging specific issues that you think may be being swallowed. For the preferred debugging method, see `Promise#done(onFulfilled, onRejected)`.
|
100 |
|
101 | `rejection-tracking.enable(options)` takes the following options:
|
102 |
|
103 | - allRejections (`boolean`) - track all exceptions, not just reference errors and type errors. Note that this has a high probability of resulting in false positives if your code loads data optimisticly
|
104 | - whitelist (`Array<ErrorConstructor>`) - this defaults to `[ReferenceError, TypeError]` but you can override it with your own list of error constructors to track.
|
105 | - `onUnhandled(id, error)` and `onHandled(id, error)` - you can use these to provide your own customised display for errors. Note that if possible you should indicate that the error was a false positive if `onHandled` is called. `onHandled` is only called if `onUnhandled` has already been called.
|
106 |
|
107 | To reduce the chance of false-positives there is a delay of up to 2 seconds before errors are logged. This means that if you attach an error handler within 2 seconds, it won't be logged as a false positive. ReferenceErrors and TypeErrors are only subject to a 100ms delay due to the higher likelihood that the error is due to programmer error.
|
108 |
|
109 | ## API
|
110 |
|
111 | Before all examples, you will need:
|
112 |
|
113 | ```js
|
114 | var Promise = require('promise');
|
115 | ```
|
116 |
|
117 | ### new Promise(resolver)
|
118 |
|
119 | This creates and returns a new promise. `resolver` must be a function. The `resolver` function is passed two arguments:
|
120 |
|
121 | 1. `resolve` should be called with a single argument. If it is called with a non-promise value then the promise is fulfilled with that value. If it is called with a promise (A) then the returned promise takes on the state of that new promise (A).
|
122 | 2. `reject` should be called with a single argument. The returned promise will be rejected with that argument.
|
123 |
|
124 | ### Static Functions
|
125 |
|
126 | These methods are invoked by calling `Promise.methodName`.
|
127 |
|
128 | #### Promise.resolve(value)
|
129 |
|
130 | (deprecated aliases: `Promise.from(value)`, `Promise.cast(value)`)
|
131 |
|
132 | Converts values and foreign promises into Promises/A+ promises. If you pass it a value then it returns a Promise for that value. If you pass it something that is close to a promise (such as a jQuery attempt at a promise) it returns a Promise that takes on the state of `value` (rejected or fulfilled).
|
133 |
|
134 | #### Promise.reject(value)
|
135 |
|
136 | Returns a rejected promise with the given value.
|
137 |
|
138 | #### Promise.all(array)
|
139 |
|
140 | Returns a promise for an array. If it is called with a single argument that `Array.isArray` then this returns a promise for a copy of that array with any promises replaced by their fulfilled values. e.g.
|
141 |
|
142 | ```js
|
143 | Promise.all([Promise.resolve('a'), 'b', Promise.resolve('c')])
|
144 | .then(function (res) {
|
145 | assert(res[0] === 'a')
|
146 | assert(res[1] === 'b')
|
147 | assert(res[2] === 'c')
|
148 | })
|
149 | ```
|
150 |
|
151 | #### Promise.denodeify(fn)
|
152 |
|
153 | _Non Standard_
|
154 |
|
155 | Takes a function which accepts a node style callback and returns a new function that returns a promise instead.
|
156 |
|
157 | e.g.
|
158 |
|
159 | ```javascript
|
160 | var fs = require('fs')
|
161 |
|
162 | var read = Promise.denodeify(fs.readFile)
|
163 | var write = Promise.denodeify(fs.writeFile)
|
164 |
|
165 | var p = read('foo.json', 'utf8')
|
166 | .then(function (str) {
|
167 | return write('foo.json', JSON.stringify(JSON.parse(str), null, ' '), 'utf8')
|
168 | })
|
169 | ```
|
170 |
|
171 | #### Promise.nodeify(fn)
|
172 |
|
173 | _Non Standard_
|
174 |
|
175 | The twin to `denodeify` is useful when you want to export an API that can be used by people who haven't learnt about the brilliance of promises yet.
|
176 |
|
177 | ```javascript
|
178 | module.exports = Promise.nodeify(awesomeAPI)
|
179 | function awesomeAPI(a, b) {
|
180 | return download(a, b)
|
181 | }
|
182 | ```
|
183 |
|
184 | If the last argument passed to `module.exports` is a function, then it will be treated like a node.js callback and not parsed on to the child function, otherwise the API will just return a promise.
|
185 |
|
186 | ### Prototype Methods
|
187 |
|
188 | These methods are invoked on a promise instance by calling `myPromise.methodName`
|
189 |
|
190 | ### Promise#then(onFulfilled, onRejected)
|
191 |
|
192 | This method follows the [Promises/A+ spec](http://promises-aplus.github.io/promises-spec/). It explains things very clearly so I recommend you read it.
|
193 |
|
194 | Either `onFulfilled` or `onRejected` will be called and they will not be called more than once. They will be passed a single argument and will always be called asynchronously (in the next turn of the event loop).
|
195 |
|
196 | If the promise is fulfilled then `onFulfilled` is called. If the promise is rejected then `onRejected` is called.
|
197 |
|
198 | The call to `.then` also returns a promise. If the handler that is called returns a promise, the promise returned by `.then` takes on the state of that returned promise. If the handler that is called returns a value that is not a promise, the promise returned by `.then` will be fulfilled with that value. If the handler that is called throws an exception then the promise returned by `.then` is rejected with that exception.
|
199 |
|
200 | #### Promise#catch(onRejected)
|
201 |
|
202 | Sugar for `Promise#then(null, onRejected)`, to mirror `catch` in synchronous code.
|
203 |
|
204 | #### Promise#done(onFulfilled, onRejected)
|
205 |
|
206 | _Non Standard_
|
207 |
|
208 | The same semantics as `.then` except that it does not return a promise and any exceptions are re-thrown so that they can be logged (crashing the application in non-browser environments)
|
209 |
|
210 | #### Promise#nodeify(callback)
|
211 |
|
212 | _Non Standard_
|
213 |
|
214 | If `callback` is `null` or `undefined` it just returns `this`. If `callback` is a function it is called with rejection reason as the first argument and result as the second argument (as per the node.js convention).
|
215 |
|
216 | This lets you write API functions that look like:
|
217 |
|
218 | ```javascript
|
219 | function awesomeAPI(foo, bar, callback) {
|
220 | return internalAPI(foo, bar)
|
221 | .then(parseResult)
|
222 | .then(null, retryErrors)
|
223 | .nodeify(callback)
|
224 | }
|
225 | ```
|
226 |
|
227 | People who use typical node.js style callbacks will be able to just pass a callback and get the expected behavior. The enlightened people can not pass a callback and will get awesome promises.
|
228 |
|
229 | ## License
|
230 |
|
231 | MIT
|