Memoize async calls with a TTL cache
JavaScript
// Cache async results for a TTL; concurrent callers share the same promise.
function memoizeAsync(fn, ttlMs) {
const cache = new Map();
return async function memoized(...args) {
const key = JSON.stringify(args);
const now = Date.now();
const hit = cache.get(key);
if (hit && hit.expires > now) return hit.value;
const value = Promise.resolve().then(() => fn.apply(this, args));
const entry = { value, expires: now + ttlMs };
cache.set(key, entry);
value.catch(() => {
if (cache.get(key) === entry) cache.delete(key);
});
return value;
};
}
let calls = 0;
const getUser = memoizeAsync(async (id) => {
calls += 1;
return { id, loadedAt: Date.now() };
}, 60_000);
Promise.all([getUser(7), getUser(7)]).then(() => {
console.log('loads:', calls); // 1
});