Created
February 17, 2021 03:17
-
-
Save dantman/f3cba7613c53102cf1a5130d44009e68 to your computer and use it in GitHub Desktop.
A hook that takes a promise and throws it according to the Suspense API
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
interface PromiseCachePending { | |
promise: Promise<void>; | |
} | |
interface PromiseCacheResolved<T> { | |
promise: Promise<void>; | |
result: T; | |
} | |
interface PromiseCacheError { | |
promise: Promise<void>; | |
error: any; | |
} | |
type PromiseCache<T> = | |
| PromiseCachePending | |
| PromiseCacheResolved<T> | |
| PromiseCacheError; | |
const PROMISE_CACHE = new WeakMap<Promise<any>, PromiseCache<any>>(); | |
/** | |
* This is a hook that takes a promise and throws it according to the Suspense API | |
* | |
* @note This is a bit of a hack since this API is really low level and the full version of Suspense isn't released yet | |
*/ | |
export default function awaitPromise<T>(promise: Promise<T>): T { | |
let promiseCache: PromiseCache<T> | undefined = PROMISE_CACHE.get(promise); | |
if (promiseCache) { | |
if ('error' in promiseCache) { | |
throw promiseCache.error; | |
} | |
if ('result' in promiseCache) { | |
return promiseCache.result; | |
} | |
throw promiseCache.promise; | |
} | |
promiseCache = { | |
promise: promise | |
.then((result) => { | |
Object.assign(promiseCache, { | |
result, | |
}); | |
}) | |
.catch((error) => { | |
Object.assign(promiseCache, { | |
error, | |
}); | |
}), | |
}; | |
PROMISE_CACHE.set(promise, promiseCache); | |
throw promiseCache.promise; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment