You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					293 lines
				
				5.8 KiB
			
		
		
			
		
	
	
					293 lines
				
				5.8 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								'use strict';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var PENDING = 'pending';
							 | 
						||
| 
								 | 
							
								var SETTLED = 'settled';
							 | 
						||
| 
								 | 
							
								var FULFILLED = 'fulfilled';
							 | 
						||
| 
								 | 
							
								var REJECTED = 'rejected';
							 | 
						||
| 
								 | 
							
								var NOOP = function () {};
							 | 
						||
| 
								 | 
							
								var isNode = typeof global !== 'undefined' && typeof global.process !== 'undefined' && typeof global.process.emit === 'function';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var asyncSetTimer = typeof setImmediate === 'undefined' ? setTimeout : setImmediate;
							 | 
						||
| 
								 | 
							
								var asyncQueue = [];
							 | 
						||
| 
								 | 
							
								var asyncTimer;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function asyncFlush() {
							 | 
						||
| 
								 | 
							
									// run promise callbacks
							 | 
						||
| 
								 | 
							
									for (var i = 0; i < asyncQueue.length; i++) {
							 | 
						||
| 
								 | 
							
										asyncQueue[i][0](asyncQueue[i][1]);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// reset async asyncQueue
							 | 
						||
| 
								 | 
							
									asyncQueue = [];
							 | 
						||
| 
								 | 
							
									asyncTimer = false;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function asyncCall(callback, arg) {
							 | 
						||
| 
								 | 
							
									asyncQueue.push([callback, arg]);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (!asyncTimer) {
							 | 
						||
| 
								 | 
							
										asyncTimer = true;
							 | 
						||
| 
								 | 
							
										asyncSetTimer(asyncFlush, 0);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function invokeResolver(resolver, promise) {
							 | 
						||
| 
								 | 
							
									function resolvePromise(value) {
							 | 
						||
| 
								 | 
							
										resolve(promise, value);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function rejectPromise(reason) {
							 | 
						||
| 
								 | 
							
										reject(promise, reason);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									try {
							 | 
						||
| 
								 | 
							
										resolver(resolvePromise, rejectPromise);
							 | 
						||
| 
								 | 
							
									} catch (e) {
							 | 
						||
| 
								 | 
							
										rejectPromise(e);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function invokeCallback(subscriber) {
							 | 
						||
| 
								 | 
							
									var owner = subscriber.owner;
							 | 
						||
| 
								 | 
							
									var settled = owner._state;
							 | 
						||
| 
								 | 
							
									var value = owner._data;
							 | 
						||
| 
								 | 
							
									var callback = subscriber[settled];
							 | 
						||
| 
								 | 
							
									var promise = subscriber.then;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (typeof callback === 'function') {
							 | 
						||
| 
								 | 
							
										settled = FULFILLED;
							 | 
						||
| 
								 | 
							
										try {
							 | 
						||
| 
								 | 
							
											value = callback(value);
							 | 
						||
| 
								 | 
							
										} catch (e) {
							 | 
						||
| 
								 | 
							
											reject(promise, e);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (!handleThenable(promise, value)) {
							 | 
						||
| 
								 | 
							
										if (settled === FULFILLED) {
							 | 
						||
| 
								 | 
							
											resolve(promise, value);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (settled === REJECTED) {
							 | 
						||
| 
								 | 
							
											reject(promise, value);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function handleThenable(promise, value) {
							 | 
						||
| 
								 | 
							
									var resolved;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									try {
							 | 
						||
| 
								 | 
							
										if (promise === value) {
							 | 
						||
| 
								 | 
							
											throw new TypeError('A promises callback cannot return that same promise.');
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (value && (typeof value === 'function' || typeof value === 'object')) {
							 | 
						||
| 
								 | 
							
											// then should be retrieved only once
							 | 
						||
| 
								 | 
							
											var then = value.then;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (typeof then === 'function') {
							 | 
						||
| 
								 | 
							
												then.call(value, function (val) {
							 | 
						||
| 
								 | 
							
													if (!resolved) {
							 | 
						||
| 
								 | 
							
														resolved = true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														if (value === val) {
							 | 
						||
| 
								 | 
							
															fulfill(promise, val);
							 | 
						||
| 
								 | 
							
														} else {
							 | 
						||
| 
								 | 
							
															resolve(promise, val);
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}, function (reason) {
							 | 
						||
| 
								 | 
							
													if (!resolved) {
							 | 
						||
| 
								 | 
							
														resolved = true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														reject(promise, reason);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												return true;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									} catch (e) {
							 | 
						||
| 
								 | 
							
										if (!resolved) {
							 | 
						||
| 
								 | 
							
											reject(promise, e);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return true;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return false;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function resolve(promise, value) {
							 | 
						||
| 
								 | 
							
									if (promise === value || !handleThenable(promise, value)) {
							 | 
						||
| 
								 | 
							
										fulfill(promise, value);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function fulfill(promise, value) {
							 | 
						||
| 
								 | 
							
									if (promise._state === PENDING) {
							 | 
						||
| 
								 | 
							
										promise._state = SETTLED;
							 | 
						||
| 
								 | 
							
										promise._data = value;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										asyncCall(publishFulfillment, promise);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function reject(promise, reason) {
							 | 
						||
| 
								 | 
							
									if (promise._state === PENDING) {
							 | 
						||
| 
								 | 
							
										promise._state = SETTLED;
							 | 
						||
| 
								 | 
							
										promise._data = reason;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										asyncCall(publishRejection, promise);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function publish(promise) {
							 | 
						||
| 
								 | 
							
									promise._then = promise._then.forEach(invokeCallback);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function publishFulfillment(promise) {
							 | 
						||
| 
								 | 
							
									promise._state = FULFILLED;
							 | 
						||
| 
								 | 
							
									publish(promise);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function publishRejection(promise) {
							 | 
						||
| 
								 | 
							
									promise._state = REJECTED;
							 | 
						||
| 
								 | 
							
									publish(promise);
							 | 
						||
| 
								 | 
							
									if (!promise._handled && isNode) {
							 | 
						||
| 
								 | 
							
										global.process.emit('unhandledRejection', promise._data, promise);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function notifyRejectionHandled(promise) {
							 | 
						||
| 
								 | 
							
									global.process.emit('rejectionHandled', promise);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @class
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								function Promise(resolver) {
							 | 
						||
| 
								 | 
							
									if (typeof resolver !== 'function') {
							 | 
						||
| 
								 | 
							
										throw new TypeError('Promise resolver ' + resolver + ' is not a function');
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (this instanceof Promise === false) {
							 | 
						||
| 
								 | 
							
										throw new TypeError('Failed to construct \'Promise\': Please use the \'new\' operator, this object constructor cannot be called as a function.');
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									this._then = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									invokeResolver(resolver, this);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Promise.prototype = {
							 | 
						||
| 
								 | 
							
									constructor: Promise,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									_state: PENDING,
							 | 
						||
| 
								 | 
							
									_then: null,
							 | 
						||
| 
								 | 
							
									_data: undefined,
							 | 
						||
| 
								 | 
							
									_handled: false,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									then: function (onFulfillment, onRejection) {
							 | 
						||
| 
								 | 
							
										var subscriber = {
							 | 
						||
| 
								 | 
							
											owner: this,
							 | 
						||
| 
								 | 
							
											then: new this.constructor(NOOP),
							 | 
						||
| 
								 | 
							
											fulfilled: onFulfillment,
							 | 
						||
| 
								 | 
							
											rejected: onRejection
							 | 
						||
| 
								 | 
							
										};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ((onRejection || onFulfillment) && !this._handled) {
							 | 
						||
| 
								 | 
							
											this._handled = true;
							 | 
						||
| 
								 | 
							
											if (this._state === REJECTED && isNode) {
							 | 
						||
| 
								 | 
							
												asyncCall(notifyRejectionHandled, this);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (this._state === FULFILLED || this._state === REJECTED) {
							 | 
						||
| 
								 | 
							
											// already resolved, call callback async
							 | 
						||
| 
								 | 
							
											asyncCall(invokeCallback, subscriber);
							 | 
						||
| 
								 | 
							
										} else {
							 | 
						||
| 
								 | 
							
											// subscribe
							 | 
						||
| 
								 | 
							
											this._then.push(subscriber);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return subscriber.then;
							 | 
						||
| 
								 | 
							
									},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									catch: function (onRejection) {
							 | 
						||
| 
								 | 
							
										return this.then(null, onRejection);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Promise.all = function (promises) {
							 | 
						||
| 
								 | 
							
									if (!Array.isArray(promises)) {
							 | 
						||
| 
								 | 
							
										throw new TypeError('You must pass an array to Promise.all().');
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return new Promise(function (resolve, reject) {
							 | 
						||
| 
								 | 
							
										var results = [];
							 | 
						||
| 
								 | 
							
										var remaining = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										function resolver(index) {
							 | 
						||
| 
								 | 
							
											remaining++;
							 | 
						||
| 
								 | 
							
											return function (value) {
							 | 
						||
| 
								 | 
							
												results[index] = value;
							 | 
						||
| 
								 | 
							
												if (!--remaining) {
							 | 
						||
| 
								 | 
							
													resolve(results);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											};
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for (var i = 0, promise; i < promises.length; i++) {
							 | 
						||
| 
								 | 
							
											promise = promises[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (promise && typeof promise.then === 'function') {
							 | 
						||
| 
								 | 
							
												promise.then(resolver(i), reject);
							 | 
						||
| 
								 | 
							
											} else {
							 | 
						||
| 
								 | 
							
												results[i] = promise;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (!remaining) {
							 | 
						||
| 
								 | 
							
											resolve(results);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									});
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Promise.race = function (promises) {
							 | 
						||
| 
								 | 
							
									if (!Array.isArray(promises)) {
							 | 
						||
| 
								 | 
							
										throw new TypeError('You must pass an array to Promise.race().');
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return new Promise(function (resolve, reject) {
							 | 
						||
| 
								 | 
							
										for (var i = 0, promise; i < promises.length; i++) {
							 | 
						||
| 
								 | 
							
											promise = promises[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (promise && typeof promise.then === 'function') {
							 | 
						||
| 
								 | 
							
												promise.then(resolve, reject);
							 | 
						||
| 
								 | 
							
											} else {
							 | 
						||
| 
								 | 
							
												resolve(promise);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									});
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Promise.resolve = function (value) {
							 | 
						||
| 
								 | 
							
									if (value && typeof value === 'object' && value.constructor === Promise) {
							 | 
						||
| 
								 | 
							
										return value;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return new Promise(function (resolve) {
							 | 
						||
| 
								 | 
							
										resolve(value);
							 | 
						||
| 
								 | 
							
									});
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Promise.reject = function (reason) {
							 | 
						||
| 
								 | 
							
									return new Promise(function (resolve, reject) {
							 | 
						||
| 
								 | 
							
										reject(reason);
							 | 
						||
| 
								 | 
							
									});
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports = Promise;
							 |