You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
88 lines
1.9 KiB
88 lines
1.9 KiB
'use strict'; |
|
const mimicFn = require('mimic-fn'); |
|
const isPromise = require('p-is-promise'); |
|
const mapAgeCleaner = require('map-age-cleaner'); |
|
|
|
const cacheStore = new WeakMap(); |
|
|
|
const defaultCacheKey = (...arguments_) => { |
|
if (arguments_.length === 0) { |
|
return '__defaultKey'; |
|
} |
|
|
|
if (arguments_.length === 1) { |
|
const [firstArgument] = arguments_; |
|
if ( |
|
firstArgument === null || |
|
firstArgument === undefined || |
|
(typeof firstArgument !== 'function' && typeof firstArgument !== 'object') |
|
) { |
|
return firstArgument; |
|
} |
|
} |
|
|
|
return JSON.stringify(arguments_); |
|
}; |
|
|
|
const mem = (fn, options) => { |
|
options = Object.assign({ |
|
cacheKey: defaultCacheKey, |
|
cache: new Map(), |
|
cachePromiseRejection: false |
|
}, options); |
|
|
|
if (typeof options.maxAge === 'number') { |
|
mapAgeCleaner(options.cache); |
|
} |
|
|
|
const {cache} = options; |
|
options.maxAge = options.maxAge || 0; |
|
|
|
const setData = (key, data) => { |
|
cache.set(key, { |
|
data, |
|
maxAge: Date.now() + options.maxAge |
|
}); |
|
}; |
|
|
|
const memoized = function (...arguments_) { |
|
const key = options.cacheKey(...arguments_); |
|
|
|
if (cache.has(key)) { |
|
return cache.get(key).data; |
|
} |
|
|
|
const cacheItem = fn.call(this, ...arguments_); |
|
|
|
setData(key, cacheItem); |
|
|
|
if (isPromise(cacheItem) && options.cachePromiseRejection === false) { |
|
// Remove rejected promises from cache unless `cachePromiseRejection` is set to `true` |
|
cacheItem.catch(() => cache.delete(key)); |
|
} |
|
|
|
return cacheItem; |
|
}; |
|
|
|
try { |
|
// The below call will throw in some host environments |
|
// See https://github.com/sindresorhus/mimic-fn/issues/10 |
|
mimicFn(memoized, fn); |
|
} catch (_) {} |
|
|
|
cacheStore.set(memoized, options.cache); |
|
|
|
return memoized; |
|
}; |
|
|
|
module.exports = mem; |
|
// TODO: Remove this for the next major release |
|
module.exports.default = mem; |
|
|
|
module.exports.clear = fn => { |
|
const cache = cacheStore.get(fn); |
|
|
|
if (cache && typeof cache.clear === 'function') { |
|
cache.clear(); |
|
} |
|
};
|
|
|