Skip to content

Instantly share code, notes, and snippets.

@itsMapleLeaf
Created November 17, 2018 03:04
Show Gist options
  • Select an option

  • Save itsMapleLeaf/d30360644801216e62a14f901c8a22b7 to your computer and use it in GitHub Desktop.

Select an option

Save itsMapleLeaf/d30360644801216e62a14f901c8a22b7 to your computer and use it in GitHub Desktop.
export interface CachedResource<I extends any[], V> {
load(...input: I): Promise<V>
loadSuspended(...input: I): V
has(...input: I): boolean
get(...input: I): V | undefined
set(item: V, ...input: I): void
invalidate(...input: I): void
clear(): void
}
export default function createCachedResource<I extends any[], V>(
loadResource: (...input: I) => Promise<V>,
hashInput?: (...input: I) => string,
): CachedResource<I, V> {
const cache = new Map<string, V>()
const errors = new Map<string, any>()
const getKeyFromInput = (...input: I) =>
hashInput ? hashInput(...input) : input.join("-")
async function load(...input: I) {
const key = getKeyFromInput(...input)
try {
errors.delete(key)
const data = cache.get(key) || (await loadResource(...input))
cache.set(key, data)
return data
} catch (error) {
errors.set(key, error)
throw error
}
}
return {
load,
loadSuspended(...input: I) {
const key = getKeyFromInput(...input)
const data = cache.get(key)
if (data) return data
const error = errors.get(key)
if (error) throw error
throw load(...input) // 👀
},
has(...input: I) {
return cache.has(getKeyFromInput(...input))
},
get(...input: I) {
return cache.get(getKeyFromInput(...input))
},
set(item: V, ...input: I) {
cache.set(getKeyFromInput(...input), item)
},
invalidate(...input: I) {
cache.delete(getKeyFromInput(...input))
},
clear() {
cache.clear()
},
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment