Today I learned that the best abstraction for a simple cache is likely a closure. I was trying to figure out a generalized way to cache things like bitcoin's blockheight and the exchange rate.
function cachedFetcher(fetcher, { cacheExpiry, forceRefreshThreshold }) { let cache = null; return async function cachedFetch(...args) { const now = Date.now(); async function fetchAndCache() { const result = await fetcher(...args); cache = { data: result, createdAt: now }; return result; } if (cache) { const age = now - cache.createdAt; if (age < cacheExpiry) { return cache.data; } else if (age < forceRefreshThreshold) { fetchAndCache().catch(console.error); return cache.data; } } return await fetchAndCache(); }; } const getBlockHeight = createCachedFetcher(fetchBlockHeight, { cacheExpiry: 60 * 1000, forceRefreshThreshold: 10 * 60 * 1000, })