aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/oncePromise.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/oncePromise.ts')
-rw-r--r--src/lib/oncePromise.ts30
1 files changed, 30 insertions, 0 deletions
diff --git a/src/lib/oncePromise.ts b/src/lib/oncePromise.ts
new file mode 100644
index 0000000..f6ce775
--- /dev/null
+++ b/src/lib/oncePromise.ts
@@ -0,0 +1,30 @@
+const ensurePromise = <T>(maybePromise: T | PromiseLike<T>): Promise<T> =>
+ typeof maybePromise === 'object' &&
+ maybePromise !== null &&
+ 'then' in maybePromise &&
+ typeof maybePromise.then === 'function' &&
+ 'catch' in maybePromise &&
+ typeof maybePromise.catch === 'function' &&
+ 'finally' in maybePromise &&
+ typeof maybePromise.finally === 'function'
+ ? (maybePromise as Promise<T>)
+ : Promise.resolve(maybePromise);
+/** Returns a function that caches successful promises until time runs out, and throws away unsuccessful ones */
+export const oncePromise = <T>(create: () => Promise<T>, timeout = -1) => {
+ let getPromise = (): Promise<T> => {
+ const oldGetPromise = getPromise,
+ promise = ensurePromise(create()).catch((e) => {
+ getPromise = oldGetPromise;
+ throw e;
+ }),
+ expires = timeout > 0 ? performance.now() + timeout : 0;
+ return (getPromise = expires
+ ? ((() =>
+ performance.now() > expires
+ ? oldGetPromise()
+ : promise) as () => Promise<T>)
+ : () => promise)();
+ };
+ return () => getPromise();
+};
+export default oncePromise;