Skip to content

Instantly share code, notes, and snippets.

@mrosata
Created February 12, 2019 18:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrosata/93f9cf3c3057481521829f40cc43fbb0 to your computer and use it in GitHub Desktop.
Save mrosata/93f9cf3c3057481521829f40cc43fbb0 to your computer and use it in GitHub Desktop.
Cache functions that return promises with a TTL
/**
* Memioze a function with a TTL
* @param func {function} The function to memioze (can return promise)
* @param ttl {number?} milliseconds to cache results (default = 30000)
* @param ttlError {number?} milliseconds to cache errors (default = ttl = 30000)
* @param initialValue {*} an optional value to return before initial func() result
* @return {{get: (function(...[*]=): Promise<*>), clear: (function(): void)}}
*/
export function memoizeWithTTL ({ func, ttl = 30000, ttlError = ttl, initialValue }) {
let cache = {}
return {
clear: (key) => {
if (key) {
cache[key] = { expires: 0, state: '', value: initialValue }
} else {
cache = {}
}
},
get: async (...args) => {
const cacheKey = crypto.createHash('sha1')
.update(JSON.stringify(args))
.digest('base64')
cache[cacheKey] = cache[cacheKey] || { expires: 0, state: '', value: initialValue }
const cachedItem = cache[cacheKey]
// If TTL has expired then get the updated value from func
if (cachedItem.expires < new Date().getTime() && cachedItem.state !== 'pending') {
cachedItem.state = 'pending'
try {
cachedItem.value = await func(...args)
cachedItem.expires = new Date().getTime() + ttl
cachedItem.state = 'resolved'
} catch (error) {
cachedItem.value = error
cachedItem.expires = new Date().getTime() + ttlError
cachedItem.state = 'rejected'
}
}
// Return the cached value
if (cachedItem.state === 'rejected') {
throw cachedItem.value
}
return cachedItem.value
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment