UNPKG

zalgo-promise

Version:
445 lines (365 loc) 10.7 kB
import { isPromise as _isPromise } from './utils'; import { onPossiblyUnhandledException as _onPossiblyUnhandledException, dispatchPossiblyUnhandledError } from './exceptions'; import { startActive, endActive, awaitActive } from './flush'; export var ZalgoPromise = /*#__PURE__*/function () { // eslint-disable-next-line flowtype/no-mutable-array function ZalgoPromise(handler) { var _this = this; this.resolved = void 0; this.rejected = void 0; this.errorHandled = void 0; this.value = void 0; this.error = void 0; this.handlers = void 0; this.dispatching = void 0; this.stack = void 0; this.resolved = false; this.rejected = false; this.errorHandled = false; this.handlers = []; if (handler) { var _result; var _error; var resolved = false; var rejected = false; var isAsync = false; startActive(); try { handler(function (res) { if (isAsync) { _this.resolve(res); } else { resolved = true; _result = res; } }, function (err) { if (isAsync) { _this.reject(err); } else { rejected = true; _error = err; } }); } catch (err) { endActive(); this.reject(err); return; } endActive(); isAsync = true; if (resolved) { // $FlowFixMe this.resolve(_result); } else if (rejected) { this.reject(_error); } } if (__DEBUG__) { try { throw new Error("ZalgoPromise"); } catch (err) { this.stack = err.stack; } } } var _proto = ZalgoPromise.prototype; _proto.resolve = function resolve(result) { if (this.resolved || this.rejected) { return this; } if (_isPromise(result)) { throw new Error('Can not resolve promise with another promise'); } this.resolved = true; this.value = result; this.dispatch(); return this; }; _proto.reject = function reject(error) { var _this2 = this; if (this.resolved || this.rejected) { return this; } if (_isPromise(error)) { throw new Error('Can not reject promise with another promise'); } if (!error) { // $FlowFixMe var _err = error && typeof error.toString === 'function' ? error.toString() : Object.prototype.toString.call(error); error = new Error("Expected reject to be called with Error, got " + _err); } this.rejected = true; this.error = error; if (!this.errorHandled) { setTimeout(function () { if (!_this2.errorHandled) { dispatchPossiblyUnhandledError(error, _this2); } }, 1); } this.dispatch(); return this; }; _proto.asyncReject = function asyncReject(error) { this.errorHandled = true; this.reject(error); return this; }; _proto.dispatch = function dispatch() { var dispatching = this.dispatching, resolved = this.resolved, rejected = this.rejected, handlers = this.handlers; if (dispatching) { return; } if (!resolved && !rejected) { return; } this.dispatching = true; startActive(); var chain = function chain(firstPromise, secondPromise) { return firstPromise.then(function (res) { secondPromise.resolve(res); }, function (err) { secondPromise.reject(err); }); }; for (var i = 0; i < handlers.length; i++) { var _handlers$i = handlers[i], onSuccess = _handlers$i.onSuccess, onError = _handlers$i.onError, promise = _handlers$i.promise; var _result2 = void 0; if (resolved) { try { _result2 = onSuccess ? onSuccess(this.value) : this.value; } catch (err) { promise.reject(err); continue; } } else if (rejected) { if (!onError) { promise.reject(this.error); continue; } try { _result2 = onError(this.error); } catch (err) { promise.reject(err); continue; } } if (_result2 instanceof ZalgoPromise && (_result2.resolved || _result2.rejected)) { var promiseResult = _result2; if (promiseResult.resolved) { promise.resolve(promiseResult.value); } else { promise.reject(promiseResult.error); } promiseResult.errorHandled = true; } else if (_isPromise(_result2)) { if (_result2 instanceof ZalgoPromise && (_result2.resolved || _result2.rejected)) { if (_result2.resolved) { promise.resolve(_result2.value); } else { promise.reject(_result2.error); } } else { // $FlowFixMe chain(_result2, promise); } } else { promise.resolve(_result2); } } handlers.length = 0; this.dispatching = false; endActive(); }; _proto.then = function then(onSuccess, onError) { if (onSuccess && typeof onSuccess !== 'function' && !onSuccess.call) { throw new Error('Promise.then expected a function for success handler'); } if (onError && typeof onError !== 'function' && !onError.call) { throw new Error('Promise.then expected a function for error handler'); } var promise = new ZalgoPromise(); this.handlers.push({ promise: promise, onSuccess: onSuccess, onError: onError }); this.errorHandled = true; this.dispatch(); return promise; }; _proto.catch = function _catch(onError) { // $FlowFixMe incompatible-call var resultPromise = this.then(undefined, onError); return resultPromise; }; _proto.finally = function _finally(onFinally) { if (onFinally && typeof onFinally !== 'function' && !onFinally.call) { throw new Error('Promise.finally expected a function'); } return this.then(function (result) { return ZalgoPromise.try(onFinally).then(function () { return result; }); }, function (err) { return ZalgoPromise.try(onFinally).then(function () { throw err; }); }); }; _proto.timeout = function timeout(time, err) { var _this3 = this; if (this.resolved || this.rejected) { return this; } var timeout = setTimeout(function () { if (_this3.resolved || _this3.rejected) { return; } _this3.reject(err || new Error("Promise timed out after " + time + "ms")); }, time); return this.then(function (result) { clearTimeout(timeout); return result; }); } // $FlowFixMe ; _proto.toPromise = function toPromise() { // $FlowFixMe if (typeof Promise === 'undefined') { throw new TypeError("Could not find Promise"); } // $FlowFixMe return Promise.resolve(this); // eslint-disable-line compat/compat }; _proto.lazy = function lazy() { this.errorHandled = true; return this; }; ZalgoPromise.resolve = function resolve(value) { if (value instanceof ZalgoPromise) { // $FlowFixMe incompatible-type-arg var _result3 = value; return _result3; } if (_isPromise(value)) { // $FlowFixMe return new ZalgoPromise(function (resolve, reject) { return value.then(resolve, reject); }); } return new ZalgoPromise().resolve(value); }; ZalgoPromise.reject = function reject(error) { return new ZalgoPromise().reject(error); }; ZalgoPromise.asyncReject = function asyncReject(error) { return new ZalgoPromise().asyncReject(error); }; ZalgoPromise.all = function all(promises) { // eslint-disable-line no-undef var promise = new ZalgoPromise(); var count = promises.length; // eslint-disable-next-line no-undef var results = [].slice(); if (!count) { promise.resolve(results); return promise; } var chain = function chain(i, firstPromise, secondPromise) { return firstPromise.then(function (res) { results[i] = res; count -= 1; if (count === 0) { promise.resolve(results); } }, function (err) { secondPromise.reject(err); }); }; for (var i = 0; i < promises.length; i++) { var prom = promises[i]; if (prom instanceof ZalgoPromise) { if (prom.resolved) { results[i] = prom.value; count -= 1; continue; } } else if (!_isPromise(prom)) { results[i] = prom; count -= 1; continue; } chain(i, ZalgoPromise.resolve(prom), promise); } if (count === 0) { promise.resolve(results); } return promise; }; ZalgoPromise.hash = function hash(promises) { // eslint-disable-line no-undef var result = {}; var awaitPromises = []; var _loop = function _loop(key) { if (promises.hasOwnProperty(key)) { var value = promises[key]; if (_isPromise(value)) { awaitPromises.push(value.then(function (res) { result[key] = res; })); } else { result[key] = value; } } }; for (var key in promises) { _loop(key); } return ZalgoPromise.all(awaitPromises).then(function () { return result; }); }; ZalgoPromise.map = function map(items, method) { // $FlowFixMe return ZalgoPromise.all(items.map(method)); }; ZalgoPromise.onPossiblyUnhandledException = function onPossiblyUnhandledException(handler) { return _onPossiblyUnhandledException(handler); }; ZalgoPromise.try = function _try(method, context, args) { if (method && typeof method !== 'function' && !method.call) { throw new Error('Promise.try expected a function'); } var result; startActive(); try { result = method.apply(context, args || []); } catch (err) { endActive(); return ZalgoPromise.reject(err); } endActive(); // $FlowFixMe incompatible-call var resultPromise = ZalgoPromise.resolve(result); return resultPromise; }; ZalgoPromise.delay = function delay(_delay) { return new ZalgoPromise(function (resolve) { setTimeout(resolve, _delay); }); }; ZalgoPromise.isPromise = function isPromise(value) { if (value && value instanceof ZalgoPromise) { return true; } return _isPromise(value); }; ZalgoPromise.flush = function flush() { return awaitActive(ZalgoPromise); }; return ZalgoPromise; }();