/* eslint-disable no-var */ /* eslint-disable no-plusplus */ /* eslint-disable prefer-arrow-callback */ /* eslint-disable prefer-template */ /* eslint-disable func-names */ /* eslint-disable object-shorthand */ (function (factory) { // eslint-disable-next-line no-unused-expressions window.Promise || (window.Promise = factory()); // eslint-disable-next-line padded-blocks }(function () { var STATUS = { PENDING: 'pending', SEALED: 'sealed', FULFILLED: 'fulfilled', REJECTED: 'rejected', }; var asyncSettimer = typeof setImmediate !== 'undefined' ? setImmediate : setTimeout; var asyncQueue = []; var asyncTimer; function NOP() { } function isArray(value) { return Array.isArray ? Array.isArray(value) : Object.prototype.toString.call(value) === '[object Array]'; } function asyncFlush() { var i = 0; // run for (; i < asyncQueue.length; i++) { asyncQueue[i][0](asyncQueue[i][1]); } // reset asyncQueue = []; asyncTimer = false; } function asyncCall(callback, arg) { asyncQueue.push([callback, arg]); if (!asyncTimer) { asyncTimer = true; asyncSettimer(asyncFlush, 0); } } function publish(promise) { var i = 0; var callbacks = promise._then; promise._then = null; for (; i < callbacks.length; i++) { // eslint-disable-next-line no-use-before-define invokeCallback(callbacks[i]); } } function publishFulfillment(promise) { promise._state = STATUS.FULFILLED; publish(promise); } function publishRejection(promise) { promise._state = STATUS.REJECTED; publish(promise); } function fulfill(promise, value) { if (promise._state === STATUS.PENDING) { promise._state = STATUS.SEALED; promise._data = value; asyncCall(publishFulfillment, promise); } } function resolve(promise, value) { // eslint-disable-next-line no-use-before-define if (promise === value || !handleThenable(promise, value)) { fulfill(promise, value); } } function reject(promise, reason) { if (promise._state === STATUS.PENDING) { promise._state = STATUS.SEALED; promise._data = reason; asyncCall(publishRejection, promise); } } function handleThenable(promise, value) { var resolved; try { if (promise === value) { throw new TypeError('A promise\'s callback cannot return that same promise'); } if (value && (typeof value === 'function' || typeof value === 'object')) { // eslint-disable-next-line vars-on-top var then = value.then; if (typeof then === 'function') { then.call(value, function (val) { if (!resolved) { resolved = true; if (value !== val) { resolve(promise, val); } else { fulfill(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 invokeResolver(fn, promise) { function resolvePromise(value) { resolve(promise, value); } function rejectPromise(reason) { reject(promise, reason); } try { fn(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 = STATUS.FULFILLED; try { value = callback(value); } catch (e) { reject(promise, e); } } if (!handleThenable(promise, value)) { if (settled === STATUS.FULFILLED) { resolve(promise, value); } else if (settled === STATUS.REJECTED) { reject(promise, value); } } } function Promise(fn) { if (!(this instanceof Promise)) { throw new TypeError(this + ' is not a promise'); } if (typeof fn !== 'function') { throw new TypeError('Promise resolver ' + fn + ' is not a function'); } this._then = []; invokeResolver(fn, this); } Promise.prototype = { _state: STATUS.PENDING, _then: null, _data: undefined, then: function (onResolver, onRejection) { var subscriber = { owner: this, then: new Promise(NOP), fulfilled: onResolver, rejected: onRejection, }; if (this._state === STATUS.FULFILLED || this._state === STATUS.REJECTED) { // already resolved asyncCall(invokeCallback, subscriber); } else { // subscribe this._then.push(subscriber); } return subscriber.then; }, // eslint-disable-next-line quote-props 'catch': function (onRejection) { return this.then(null, onRejection); }, }; // eslint-disable-next-line no-extend-native Object.defineProperty(Promise.prototype, 'constructor', { value: Promise }); Promise.all = function (promises) { var This = this; if (!isArray(promises)) { throw new TypeError(promises + ' is not an array'); } return new This(function (onresolve, onreject) { var results = []; var remaining = 0; var i = 0; var promise; function resolver(index) { remaining++; return function (value) { results[index] = value; if (!--remaining) { onresolve(results); } }; } for (; i < promises.length; i++) { promise = promises[i]; if (promise && typeof promise.then === 'function') { promise.then(resolver(i), onreject); } else { results[i] = promise; } } if (!remaining) { onresolve(results); } }); }; Promise.race = function (promises) { var This = this; if (!isArray(promises)) { throw new TypeError(promises + ' is not an array'); } return new This(function (onresolve, onreject) { var i = 0; var promise; for (; i < promises.length; i++) { promise = promises[i]; if (promise && typeof promise.then === 'function') { promise.then(onresolve, onreject); } else { onresolve(promise); } } }); }; Promise.resolve = function (value) { var This = this; if (value && typeof value === 'object' && value.constructor === This) { return value; } return new This(function (onresolve) { onresolve(value); }); }; Promise.reject = function (reason) { var This = this; return new This(function (onresolve, onreject) { onreject(reason); }); }; return Promise; }));