-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
64 lines (57 loc) · 1.7 KB
/
index.js
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
61
62
63
64
// @ts-check
import React from 'react';
/**
* @template T
*/
class PromiseWithResolverAccess {
constructor() {
/** @type {undefined | null | ((arg: T) => void)} */
this.resolver = undefined;
/** @type {undefined | null | ((arg: any) => void)} */
this.rejecter = undefined;
/** @readonly @type {Promise<T>} */
this.promise = new Promise((resolve, reject) => {
this.resolver = resolve;
this.rejecter = reject;
});
}
/**
* @param {T} res
*/
resolve (res) {
this.checkResolverAndRejecter();
/** @type {(arg: T) => void}*/(this.resolver)(res);
this.resolver = null;
}
reject (err) {
this.checkResolverAndRejecter();
/** @type {(arg: any) => void}*/(this.rejecter)(err);
this.rejecter = null;
}
/**
*
* @param {((value: T) => any) | undefined | null} [resolve]
* @param {((reason: any) => any) | undefined | null} [reject]
* @return {PromiseLike<T>}
*/
then (resolve, reject) {
return this.promise.then(resolve, reject);
}
checkResolverAndRejecter() {
const sharedText = 'has already been called, can\'t call it twice in the same request';
if (this.resolver === null) throw new Error(`resolve ${sharedText}`);
if (this.rejecter === null) throw new Error(`reject ${sharedText}`);
}
}
/**
* @template T
* @param {any} [cache]
* @returns {() => PromiseWithResolverAccess<T>}
*/
// @param {<U extends ((...args: any[]) => any)>(func: U) => U} [cache]
export const createCachedPromiseGetter = (cache) => {
const getPromise = () => new PromiseWithResolverAccess();
// @ts-ignore
return (cache ?? /** @type {NonNullable<typeof cache>} */ (React.cache))(getPromise);
};
export default createCachedPromiseGetter;