UNPKG

promise-swr

Version:

Caches a promise-returning function with a stale-while-revalidate strategy

73 lines (65 loc) 2.38 kB
'use strict' /** * Caches a promise-returning function with a stale-while-revalidate strategy. * * Every time the wrapper function is called, if there is no data in the cache * or if the age of the data is too old, new data will be fetched and returned. * If the age of the data is greater than the revalidation threshold but still * valid, it will be returned and new data will be fetched in the background. If * the data is below the revalidation threshold, it is fresh and is returned * right away. * * @template {any[]} T Tuple of argument types for the wrapped function. * @template K Type of the cache key. * @template R Return type of the wrapped function. * @param {(...args: T) => R | Promise<R>} fn The function to cache. * @param {object} [options] The options. * @param {Map<K, any>} [options.cache] The cache. Follows the `Map` interface. * @param {number} [options.maxAge] The max time to cache any result in ms. * @param {(...args: T) => K} [options.resolver] The key resolver function. * @param {number} [options.revalidate] The max time to wait until revalidating. * @returns {(...args: T) => Promise<R>} A function that caches `fn`. */ function pSwr(fn, options = {}) { const { cache = new Map(), maxAge = Infinity, resolver = (...args) => args[0], revalidate = 0 } = options return function (...args) { const key = resolver(...args) const cached = cache.get(key) const keyAge = !cached || cached.revalidating ? 0 : Date.now() - cached.timestamp if (!cached || keyAge > maxAge) { const _cached = { data: Promise.resolve(fn(...args)), revalidating: true, timestamp: Infinity } cache.set(key, _cached) _cached.data .then(function () { _cached.timestamp = Date.now() _cached.revalidating = false }) .catch(function () { cache.delete(key) }) } else if (keyAge > revalidate && !cached.revalidating) { cached.revalidating = true Promise.resolve(fn(...args)) .then(function (result) { cached.data = Promise.resolve(result) cached.timestamp = Date.now() cached.revalidating = false }) .catch(function () { cached.revalidating = false }) } return cache.get(key).data } } module.exports = pSwr