Last active
November 1, 2020 18:31
-
-
Save ccnokes/b972aaed452b507749cf1013082296a9 to your computer and use it in GitHub Desktop.
A memoize function is only as good as its cache
This file contains 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
// NOTE can't use lodash.memoize because we need 2 caches and v2 doesn't support replacing the cache implementation | |
// TS type note: the below type is inspired by Lodash v4 types | |
function memoize<T extends (...args: any) => any>(fn: T, resolver?: (...args: any[]) => any) { | |
let objectCache = new WeakMap<any, any>(); // WeakMap can only store objects as keys and allows the objects to get GC'ed out | |
let primitiveCache = new Map<any, any>(); // Map can store anything as a key but no auto GC | |
return function(...args: Parameters<T>): ReturnType<T> { | |
// just in case things got out of hand, dump the cache if too many entries | |
if (primitiveCache.size > 10000) { | |
primitiveCache.clear(); | |
} | |
let key = resolver ? resolver(args) : args[0]; | |
let cache = typeof key === 'object' ? objectCache : primitiveCache; | |
if (cache.has(key)) { | |
// console.count(`cache hit`); | |
return cache.get(key); | |
} else { | |
// console.count(`cache miss`); | |
let result = fn.apply(null, args); | |
// don't allow empty/nulls/NaNs as keys | |
if (key != null && key !== '' && !(typeof key === 'number' && isNaN(key))) { | |
cache.set(key, result); | |
} | |
return result; | |
} | |
}; | |
} | |
// this memoize better supports use cases like this out of the box | |
// it'll cache the string in the primitive cache and the Thing in objectCache | |
let doStuff = memoize((stringOrThing: string | Thing) => { /*...*/ }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment