16 import all from './promise/all';
17 import race from './promise/race';
18 import Resolve from './promise/resolve';
19 import Reject from './promise/reject';
20 import then from './then';
22 function needsResolver() {
23 throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');
27 throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");
31 Promise objects represent the eventual result of an asynchronous operation. The
32 primary way of interacting with a promise is through its `then` method, which
33 registers callbacks to receive either a promise's eventual value or the reason
34 why the promise cannot be fulfilled.
39 - `promise` is an object or function with a `then` method whose behavior conforms to this specification.
40 - `thenable` is an object or function that defines a `then` method.
41 - `value` is any legal JavaScript value (including undefined, a thenable, or a promise).
42 - `exception` is a value that is thrown using the throw statement.
43 - `reason` is a value that indicates why a promise was rejected.
44 - `settled` the final resting state of a promise, fulfilled or rejected.
46 A promise can be in one of three states: pending, fulfilled, or rejected.
48 Promises that are fulfilled have a fulfillment value and are in the fulfilled
49 state. Promises that are rejected have a rejection reason and are in the
50 rejected state. A fulfillment value is never a thenable.
52 Promises can also be said to *resolve* a value. If this value is also a
53 promise, then the original promise's settled state will match the value's
54 settled state. So a promise that *resolves* a promise that rejects will
55 itself reject, and a promise that *resolves* a promise that fulfills will
63 let promise = new Promise(function(resolve, reject) {
71 promise.then(function(value) {
81 Promises shine when abstracting away asynchronous interactions such as
85 function getJSON(url) {
86 return new Promise(function(resolve, reject){
87 let xhr = new XMLHttpRequest();
90 xhr.onreadystatechange = handler;
91 xhr.responseType = 'json';
92 xhr.setRequestHeader('Accept', 'application/json');
96 if (this.readyState === this.DONE) {
97 if (this.status === 200) {
98 resolve(this.response);
100 reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']'));
107 getJSON('/posts.json').then(function(json) {
109 }, function(reason) {
114 Unlike callbacks, promises are great composable primitives.
120 ]).then(function(values){
121 values[0] // => postsJSON
122 values[1] // => commentsJSON
129 @param {Function} resolver
135 constructor(resolver) {
136 this[PROMISE_ID] = nextId();
137 this._result = this._state = undefined;
138 this._subscribers = [];
140 if (noop !== resolver) {
141 typeof resolver !== 'function' && needsResolver();
142 this instanceof Promise ? initializePromise(this, resolver) : needsNew();
147 The primary way of interacting with a promise is through its `then` method,
148 which registers callbacks to receive either a promise's eventual value or the
149 reason why the promise cannot be fulfilled.
152 findUser().then(function(user){
155 // user is unavailable, and you are given the reason why
162 The return value of `then` is itself a promise. This second, 'downstream'
163 promise is resolved with the return value of the first promise's fulfillment
164 or rejection handler, or rejected if the handler throws an exception.
167 findUser().then(function (user) {
169 }, function (reason) {
170 return 'default name';
171 }).then(function (userName) {
172 // If `findUser` fulfilled, `userName` will be the user's name, otherwise it
173 // will be `'default name'`
176 findUser().then(function (user) {
177 throw new Error('Found user, but still unhappy');
178 }, function (reason) {
179 throw new Error('`findUser` rejected and we're unhappy');
180 }).then(function (value) {
182 }, function (reason) {
183 // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.
184 // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'.
187 If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream.
190 findUser().then(function (user) {
191 throw new PedagogicalException('Upstream error');
192 }).then(function (value) {
194 }).then(function (value) {
196 }, function (reason) {
197 // The `PedgagocialException` is propagated all the way down to here
204 Sometimes the value you want to propagate to a downstream promise can only be
205 retrieved asynchronously. This can be achieved by returning a promise in the
206 fulfillment or rejection handler. The downstream promise will then be pending
207 until the returned promise is settled. This is called *assimilation*.
210 findUser().then(function (user) {
211 return findCommentsByAuthor(user);
212 }).then(function (comments) {
213 // The user's comments are now available
217 If the assimliated promise rejects, then the downstream promise will also reject.
220 findUser().then(function (user) {
221 return findCommentsByAuthor(user);
222 }).then(function (comments) {
223 // If `findCommentsByAuthor` fulfills, we'll have the value here
224 }, function (reason) {
225 // If `findCommentsByAuthor` rejects, we'll have the reason here
238 result = findResult();
248 findResult(function(result, err){
260 findResult().then(function(result){
276 author = findAuthor();
277 books = findBooksByAuthor(author);
288 function foundBooks(books) {
292 function failure(reason) {
296 findAuthor(function(author, err){
302 findBoooksByAuthor(author, function(books, err) {
325 then(findBooksByAuthor).
326 then(function(books){
328 }).catch(function(reason){
329 // something went wrong
334 @param {Function} onFulfilled
335 @param {Function} onRejected
341 `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same
342 as the catch block of a try/catch statement.
345 function findAuthor(){
346 throw new Error('couldn't find that author');
353 // something went wrong
356 // async with promises
357 findAuthor().catch(function(reason){
358 // something went wrong
363 @param {Function} onRejection
368 return this.then(null, onRejection);
372 `finally` will be invoked regardless of the promise's fate just as native
373 try/catch/finally behaves
379 if (Math.random() > 0.5) {
386 return findAuthor(); // succeed or fail
388 return findOtherAuther();
391 // doesn't affect the return value
395 Asynchronous example:
398 findAuthor().catch(function(reason){
399 return findOtherAuther();
400 }).finally(function(){
401 // author was either found, or not
406 @param {Function} callback
411 let constructor = promise.constructor;
413 if ( isFunction(callback) ) {
414 return promise.then(value => constructor.resolve(callback()).then(() => value),
415 reason => constructor.resolve(callback()).then(() => { throw reason; }));
418 return promise.then(callback, callback);
422 Promise.prototype.then = then;
423 export default Promise;
426 Promise.resolve = Resolve;
427 Promise.reject = Reject;
428 Promise._setScheduler = setScheduler;
429 Promise._setAsap = setAsap;
430 Promise._asap = asap;