feat: improve memoize cache api and types
This commit is contained in:
parent
9289e7652e
commit
c0cf85de70
1 changed files with 50 additions and 27 deletions
|
|
@ -1,6 +1,7 @@
|
|||
export const memoizeConfig = {
|
||||
isCacheDisabled: false,
|
||||
};
|
||||
/**
|
||||
* For testing purposes, it is possible to disable caching.
|
||||
*/
|
||||
let shouldCache = true;
|
||||
|
||||
/**
|
||||
* @param {object|any[]|string} arg
|
||||
|
|
@ -13,37 +14,59 @@ function isObject(arg) {
|
|||
* @param {object|any[]|string} arg
|
||||
*/
|
||||
function createCachableArg(arg) {
|
||||
if (isObject(arg)) {
|
||||
try {
|
||||
return JSON.stringify(arg);
|
||||
} catch {
|
||||
return arg;
|
||||
}
|
||||
if (!isObject(arg)) return arg;
|
||||
try {
|
||||
return JSON.stringify(arg);
|
||||
} catch {
|
||||
return arg;
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @type {<T>(functionToMemoize:T, opts?:{ storage?:object; serializeObjects?: boolean }) => T}
|
||||
*/
|
||||
export function memoize(functionToMemoize, { storage = {}, serializeObjects = false } = {}) {
|
||||
// @ts-ignore
|
||||
// @ts-expect-erro
|
||||
// eslint-disable-next-line func-names
|
||||
return function () {
|
||||
// eslint-disable-next-line prefer-rest-params
|
||||
const args = [...arguments];
|
||||
const cachableArgs = !serializeObjects ? args : args.map(createCachableArg);
|
||||
// Allow disabling of cache for testing purposes
|
||||
// @ts-ignore
|
||||
if (!memoizeConfig.isCacheDisabled && cachableArgs in storage) {
|
||||
// @ts-ignore
|
||||
return storage[cachableArgs];
|
||||
return /** @type {* & T} */ (
|
||||
function memoizedFn() {
|
||||
// eslint-disable-next-line prefer-rest-params
|
||||
const args = [...arguments];
|
||||
const cachableArgs = !serializeObjects ? args : args.map(createCachableArg);
|
||||
// Allow disabling of cache for testing purposes
|
||||
// @ts-expect-error
|
||||
if (shouldCache && cachableArgs in storage) {
|
||||
// @ts-expect-error
|
||||
return storage[cachableArgs];
|
||||
}
|
||||
// @ts-expect-error
|
||||
const outcome = functionToMemoize.apply(this, args);
|
||||
// @ts-expect-error
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
storage[cachableArgs] = outcome;
|
||||
return outcome;
|
||||
}
|
||||
// @ts-ignore
|
||||
const outcome = functionToMemoize.apply(this, args);
|
||||
// @ts-ignore
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
storage[cachableArgs] = outcome;
|
||||
return outcome;
|
||||
};
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* For testing purposes, it is possible to disable caching.
|
||||
*/
|
||||
memoize.disableCaching = () => {
|
||||
shouldCache = false;
|
||||
};
|
||||
/**
|
||||
* Once testing is done, it is possible to restore caching.
|
||||
*/
|
||||
memoize.restoreCaching = initialValue => {
|
||||
shouldCache = initialValue || true;
|
||||
};
|
||||
|
||||
Object.defineProperty(memoize, 'isCacheEnabled', {
|
||||
// writable: false,
|
||||
// enumerable: true,
|
||||
get() {
|
||||
return shouldCache;
|
||||
},
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue