const ensurePromise = (maybePromise: T | PromiseLike): Promise => 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) : Promise.resolve(maybePromise); /** Returns a function that caches successful promises until time runs out, and throws away unsuccessful ones */ export const oncePromise = (create: () => Promise, timeout = -1) => { let getPromise = (): Promise => { 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) : () => promise)(); }; return () => getPromise(); }; export default oncePromise;