UNPKG

@splitsoftware/splitio-commons

Version:
61 lines (54 loc) 2.44 kB
/** * wraps a given promise in a new one with a default onRejected function, * that handles the promise rejection if not other onRejected handler is provided. * * Caveats: * - There are some cases where the `defaultOnRejected` handler is not invoked * and the promise rejection must be handled by the user (same as the Promise spec): * - using async/await syntax with a transpiler to Promises * - setting an `onFinally` handler as the first handler (e.g. `promiseWrapper(Promise.reject()).finally(...)`) * - setting more than one handler with at least one of them being an onRejected handler * - If the wrapped promise is rejected when using native async/await syntax, the `defaultOnRejected` handler is invoked * and neither the catch block nor the remaining try block are executed. * * @param customPromise - promise to wrap * @param defaultOnRejected - default onRejected function * @returns a promise that doesn't need to be handled for rejection (except when using async/await syntax) and * includes a method named `hasOnFulfilled` that returns true if the promise has attached an onFulfilled handler. */ export function promiseWrapper<T>(customPromise: Promise<T>, defaultOnRejected: (_: any) => any): Promise<T> & { hasOnFulfilled: () => boolean } { let hasOnFulfilled = false; let hasOnRejected = false; function chain(promise: Promise<T>): Promise<T> { const newPromise: Promise<T> = new Promise((res, rej) => { return promise.then( res, function (value) { if (hasOnRejected) { rej(value); } else { defaultOnRejected(value); } } ); }); const originalThen = newPromise.then; // Using `defineProperty` in case Promise.prototype.then property is not writable Object.defineProperty(newPromise, 'then', { value: function (onfulfilled: any, onrejected: any) { const result: Promise<any> = originalThen.call(newPromise, onfulfilled, onrejected); if (typeof onfulfilled === 'function') hasOnFulfilled = true; if (typeof onrejected === 'function') { hasOnRejected = true; return result; } else { return chain(result); } } }); return newPromise; } const result = chain(customPromise) as Promise<T> & { hasOnFulfilled: () => boolean }; result.hasOnFulfilled = () => hasOnFulfilled; return result; }