Skip to content

Instantly share code, notes, and snippets.

@raibima
Last active October 30, 2019 04:47
Show Gist options
  • Select an option

  • Save raibima/7aa4f62e14be8e71535da9672ef89afb to your computer and use it in GitHub Desktop.

Select an option

Save raibima/7aa4f62e14be8e71535da9672ef89afb to your computer and use it in GitHub Desktop.
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