$ snippet memoize-lru

Memoize a function with an LRU cache

Cache expensive results by argument, cap the cache size, evict least-recently-used entries, and support async functions.

JavaScript
/**
 * memoize(fn, { max: 100, key: (...args) => string })
 * Works for sync and async fns (promises are cached; rejected ones are evicted).
 */
function memoize(fn, { max = 100, key = (...args) => JSON.stringify(args) } = {}) {
  const cache = new Map();          // Map preserves insertion order → cheap LRU
  const memoized = function (...args) {
    const k = key(...args);
    if (cache.has(k)) {
      const v = cache.get(k);
      cache.delete(k); cache.set(k, v);   // move to most-recent
      return v;
    }
    const result = fn.apply(this, args);
    cache.set(k, result);
    if (result instanceof Promise) result.catch(() => cache.delete(k));
    if (cache.size > max) cache.delete(cache.keys().next().value);   // evict oldest
    return result;
  };
  memoized.clear = () => cache.clear();
  memoized.cache = cache;
  return memoized;
}

How it works

A Map keeps keys in insertion order, so "least recently used" is simply the first key — delete-and-reinsert on every hit moves an entry to the end. Caching the promise itself (not the resolved value) means ten simultaneous calls with the same arguments trigger one request, and the rejection handler stops a failed call from being cached forever.

Gotchas

Try it
Result
Ad slot