18 import all from './promise/all';
19 import race from './promise/race';
20 import Resolve from './promise/resolve';
21 import Reject from './promise/reject';
22 import then from './then';
25 function needsResolver() {
26 throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');
30 throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");
33 export default Promise;
35 Promise objects represent the eventual result of an asynchronous operation. The
36 primary way of interacting with a promise is through its `then` method, which
37 registers callbacks to receive either a promise's eventual value or the reason
38 why the promise cannot be fulfilled.
43 - `promise` is an object or function with a `then` method whose behavior conforms to this specification.
44 - `thenable` is an object or function that defines a `then` method.
45 - `value` is any legal JavaScript value (including undefined, a thenable, or a promise).
46 - `exception` is a value that is thrown using the throw statement.
47 - `reason` is a value that indicates why a promise was rejected.
48 - `settled` the final resting state of a promise, fulfilled or rejected.
50 A promise can be in one of three states: pending, fulfilled, or rejected.
52 Promises that are fulfilled have a fulfillment value and are in the fulfilled
53 state. Promises that are rejected have a rejection reason and are in the
54 rejected state. A fulfillment value is never a thenable.
56 Promises can also be said to *resolve* a value. If this value is also a
57 promise, then the original promise's settled state will match the value's
58 settled state. So a promise that *resolves* a promise that rejects will
59 itself reject, and a promise that *resolves* a promise that fulfills will
67 var promise = new Promise(function(resolve, reject) {
75 promise.then(function(value) {
85 Promises shine when abstracting away asynchronous interactions such as
89 function getJSON(url) {
90 return new Promise(function(resolve, reject){
91 var xhr = new XMLHttpRequest();
94 xhr.onreadystatechange = handler;
95 xhr.responseType = 'json';
96 xhr.setRequestHeader('Accept', 'application/json');
100 if (this.readyState === this.DONE) {
101 if (this.status === 200) {
102 resolve(this.response);
104 reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']'));
111 getJSON('/posts.json').then(function(json) {
113 }, function(reason) {
118 Unlike callbacks, promises are great composable primitives.
124 ]).then(function(values){
125 values[0] // => postsJSON
126 values[1] // => commentsJSON
133 @param {function} resolver
137 function Promise(resolver) {
138 this[PROMISE_ID] = nextId();
139 this._result = this._state = undefined;
140 this._subscribers = [];
142 if (noop !== resolver) {
143 typeof resolver !== 'function' && needsResolver();
144 this instanceof Promise ? initializePromise(this, resolver) : needsNew();
150 Promise.resolve = Resolve;
151 Promise.reject = Reject;
152 Promise._setScheduler = setScheduler;
153 Promise._setAsap = setAsap;
154 Promise._asap = asap;
156 Promise.prototype = {
157 constructor: Promise,
160 The primary way of interacting with a promise is through its `then` method,
161 which registers callbacks to receive either a promise's eventual value or the
162 reason why the promise cannot be fulfilled.
165 findUser().then(function(user){
168 // user is unavailable, and you are given the reason why
175 The return value of `then` is itself a promise. This second, 'downstream'
176 promise is resolved with the return value of the first promise's fulfillment
177 or rejection handler, or rejected if the handler throws an exception.
180 findUser().then(function (user) {
182 }, function (reason) {
183 return 'default name';
184 }).then(function (userName) {
185 // If `findUser` fulfilled, `userName` will be the user's name, otherwise it
186 // will be `'default name'`
189 findUser().then(function (user) {
190 throw new Error('Found user, but still unhappy');
191 }, function (reason) {
192 throw new Error('`findUser` rejected and we're unhappy');
193 }).then(function (value) {
195 }, function (reason) {
196 // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.
197 // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'.
200 If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream.
203 findUser().then(function (user) {
204 throw new PedagogicalException('Upstream error');
205 }).then(function (value) {
207 }).then(function (value) {
209 }, function (reason) {
210 // The `PedgagocialException` is propagated all the way down to here
217 Sometimes the value you want to propagate to a downstream promise can only be
218 retrieved asynchronously. This can be achieved by returning a promise in the
219 fulfillment or rejection handler. The downstream promise will then be pending
220 until the returned promise is settled. This is called *assimilation*.
223 findUser().then(function (user) {
224 return findCommentsByAuthor(user);
225 }).then(function (comments) {
226 // The user's comments are now available
230 If the assimliated promise rejects, then the downstream promise will also reject.
233 findUser().then(function (user) {
234 return findCommentsByAuthor(user);
235 }).then(function (comments) {
236 // If `findCommentsByAuthor` fulfills, we'll have the value here
237 }, function (reason) {
238 // If `findCommentsByAuthor` rejects, we'll have the reason here
251 result = findResult();
261 findResult(function(result, err){
273 findResult().then(function(result){
289 author = findAuthor();
290 books = findBooksByAuthor(author);
301 function foundBooks(books) {
305 function failure(reason) {
309 findAuthor(function(author, err){
315 findBoooksByAuthor(author, function(books, err) {
338 then(findBooksByAuthor).
339 then(function(books){
341 }).catch(function(reason){
342 // something went wrong
347 @param {Function} onFulfilled
348 @param {Function} onRejected
355 `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same
356 as the catch block of a try/catch statement.
359 function findAuthor(){
360 throw new Error('couldn't find that author');
367 // something went wrong
370 // async with promises
371 findAuthor().catch(function(reason){
372 // something went wrong
377 @param {Function} onRejection
381 'catch': function(onRejection) {
382 return this.then(null, onRejection);