Last active
October 30, 2019 04:47
-
-
Save raibima/7aa4f62e14be8e71535da9672ef89afb to your computer and use it in GitHub Desktop.
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
| function createService<F extends (...args: any[]) => Promise<any>>(fn: F) { | |
| type Result = PromiseType<ReturnType<typeof fn>>; | |
| type Entry = Result | Promise<void> | Error; | |
| // const cache = new LRU<string, Entry>({maxSize: 5}); | |
| const cache = new Map(); | |
| return { | |
| call(...args: Parameters<typeof fn>): Result { | |
| const key = JSON.stringify(args); | |
| const hit = cache.get(key); | |
| if (!hit) { | |
| const promise = fn(...args).then( | |
| r => { | |
| cache.set(key, r); | |
| }, | |
| e => { | |
| cache.set(key, e); | |
| }, | |
| ); | |
| cache.set(key, promise); | |
| throw promise; | |
| } | |
| if (hit instanceof Error) { | |
| throw hit; | |
| } | |
| if (isPromise(hit)) { | |
| throw hit; | |
| } | |
| return hit; | |
| }, | |
| preload(...args: Parameters<typeof fn>) { | |
| console.log('preload'); | |
| const key = JSON.stringify(args); | |
| if (cache.has(key)) { | |
| return; | |
| } | |
| const promise = fn(...args).then( | |
| r => { | |
| console.log('resolve'); | |
| cache.set(key, r); | |
| }, | |
| e => { | |
| console.log('error'); | |
| cache.set(key, e); | |
| }, | |
| ); | |
| console.log('pending'); | |
| cache.set(key, promise); | |
| }, | |
| usePreloaded(...args: Parameters<typeof fn>): Result { | |
| const key = JSON.stringify(args); | |
| if (!cache.has(key)) { | |
| throw new Error( | |
| `usePreloaded can only retrieve result that has been preloaded beforehand`, | |
| ); | |
| } | |
| const hit = cache.get(key); | |
| if (isPromise(hit)) { | |
| throw hit; | |
| } | |
| if (hit instanceof Error) { | |
| throw hit; | |
| } | |
| return hit; | |
| }, | |
| useRefresh() { | |
| const forceUpdate = useForceUpdate(); | |
| return useCallback(() => { | |
| cache.clear(); | |
| forceUpdate(); | |
| }, [forceUpdate]); | |
| }, | |
| debug() { | |
| console.log(cache); | |
| }, | |
| }; | |
| } | |
| function isPromise(val: any): val is Promise<any> { | |
| return val && val.then === 'function'; | |
| } | |
| function useForceUpdate() { | |
| const [, set] = useState(0); | |
| return useCallback(() => set(n => n + 1), []); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment