-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathwrapper.ts
More file actions
60 lines (54 loc) · 2.39 KB
/
wrapper.ts
File metadata and controls
60 lines (54 loc) · 2.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/**
* 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;
}