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.");
34 Promise objects represent the eventual result of an asynchronous operation. The
35 primary way of interacting with a promise is through its `then` method, which
36 registers callbacks to receive either a promise's eventual value or the reason
37 why the promise cannot be fulfilled.
42 - `promise` is an object or function with a `then` method whose behavior conforms to this specification.
43 - `thenable` is an object or function that defines a `then` method.
44 - `value` is any legal JavaScript value (including undefined, a thenable, or a promise).
45 - `exception` is a value that is thrown using the throw statement.
46 - `reason` is a value that indicates why a promise was rejected.
47 - `settled` the final resting state of a promise, fulfilled or rejected.
49 A promise can be in one of three states: pending, fulfilled, or rejected.
51 Promises that are fulfilled have a fulfillment value and are in the fulfilled
52 state. Promises that are rejected have a rejection reason and are in the
53 rejected state. A fulfillment value is never a thenable.
55 Promises can also be said to *resolve* a value. If this value is also a
56 promise, then the original promise's settled state will match the value's
57 settled state. So a promise that *resolves* a promise that rejects will
58 itself reject, and a promise that *resolves* a promise that fulfills will
66 let promise = new Promise(function(resolve, reject) {
74 promise.then(function(value) {
84 Promises shine when abstracting away asynchronous interactions such as
88 function getJSON(url) {
89 return new Promise(function(resolve, reject){
90 let xhr = new XMLHttpRequest();
93 xhr.onreadystatechange = handler;
94 xhr.responseType = 'json';
95 xhr.setRequestHeader('Accept', 'application/json');
99 if (this.readyState === this.DONE) {
100 if (this.status === 200) {
101 resolve(this.response);
103 reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']'));
110 getJSON('/posts.json').then(function(json) {
112 }, function(reason) {
117 Unlike callbacks, promises are great composable primitives.
123 ]).then(function(values){
124 values[0] // => postsJSON
125 values[1] // => commentsJSON
132 @param {function} resolver
136 export default function Promise(resolver) {
137 this[PROMISE_ID] = nextId();
138 this._result = this._state = undefined;
139 this._subscribers = [];
141 if (noop !== resolver) {
142 typeof resolver !== 'function' && needsResolver();
143 this instanceof Promise ? initializePromise(this, resolver) : needsNew();
149 Promise.resolve = Resolve;
150 Promise.reject = Reject;
151 Promise._setScheduler = setScheduler;
152 Promise._setAsap = setAsap;
153 Promise._asap = asap;
155 Promise.prototype = {
156 constructor: Promise,
159 The primary way of interacting with a promise is through its `then` method,
160 which registers callbacks to receive either a promise's eventual value or the
161 reason why the promise cannot be fulfilled.
164 findUser().then(function(user){
167 // user is unavailable, and you are given the reason why
174 The return value of `then` is itself a promise. This second, 'downstream'
175 promise is resolved with the return value of the first promise's fulfillment
176 or rejection handler, or rejected if the handler throws an exception.
179 findUser().then(function (user) {
181 }, function (reason) {
182 return 'default name';
183 }).then(function (userName) {
184 // If `findUser` fulfilled, `userName` will be the user's name, otherwise it
185 // will be `'default name'`
188 findUser().then(function (user) {
189 throw new Error('Found user, but still unhappy');
190 }, function (reason) {
191 throw new Error('`findUser` rejected and we're unhappy');
192 }).then(function (value) {
194 }, function (reason) {
195 // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.
196 // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'.
199 If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream.
202 findUser().then(function (user) {
203 throw new PedagogicalException('Upstream error');
204 }).then(function (value) {
206 }).then(function (value) {
208 }, function (reason) {
209 // The `PedgagocialException` is propagated all the way down to here
216 Sometimes the value you want to propagate to a downstream promise can only be
217 retrieved asynchronously. This can be achieved by returning a promise in the
218 fulfillment or rejection handler. The downstream promise will then be pending
219 until the returned promise is settled. This is called *assimilation*.
222 findUser().then(function (user) {
223 return findCommentsByAuthor(user);
224 }).then(function (comments) {
225 // The user's comments are now available
229 If the assimliated promise rejects, then the downstream promise will also reject.
232 findUser().then(function (user) {
233 return findCommentsByAuthor(user);
234 }).then(function (comments) {
235 // If `findCommentsByAuthor` fulfills, we'll have the value here
236 }, function (reason) {
237 // If `findCommentsByAuthor` rejects, we'll have the reason here
250 result = findResult();
260 findResult(function(result, err){
272 findResult().then(function(result){
288 author = findAuthor();
289 books = findBooksByAuthor(author);
300 function foundBooks(books) {
304 function failure(reason) {
308 findAuthor(function(author, err){
314 findBoooksByAuthor(author, function(books, err) {
337 then(findBooksByAuthor).
338 then(function(books){
340 }).catch(function(reason){
341 // something went wrong
346 @param {Function} onFulfilled
347 @param {Function} onRejected
354 `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same
355 as the catch block of a try/catch statement.
358 function findAuthor(){
359 throw new Error('couldn't find that author');
366 // something went wrong
369 // async with promises
370 findAuthor().catch(function(reason){
371 // something went wrong
376 @param {Function} onRejection
381 return this.then(null, onRejection);