feat: improve memoize cache api and types

This commit is contained in:
Thijs Louisse 2024-05-08 14:27:34 +02:00
parent 9289e7652e
commit c0cf85de70

View file

@ -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 * @param {object|any[]|string} arg
@ -13,37 +14,59 @@ function isObject(arg) {
* @param {object|any[]|string} arg * @param {object|any[]|string} arg
*/ */
function createCachableArg(arg) { function createCachableArg(arg) {
if (isObject(arg)) { if (!isObject(arg)) return arg;
try { try {
return JSON.stringify(arg); return JSON.stringify(arg);
} catch { } catch {
return arg; return arg;
}
} }
return arg;
} }
/** /**
* @template T
* @type {<T>(functionToMemoize:T, opts?:{ storage?:object; serializeObjects?: boolean }) => T} * @type {<T>(functionToMemoize:T, opts?:{ storage?:object; serializeObjects?: boolean }) => T}
*/ */
export function memoize(functionToMemoize, { storage = {}, serializeObjects = false } = {}) { export function memoize(functionToMemoize, { storage = {}, serializeObjects = false } = {}) {
// @ts-ignore // @ts-expect-erro
// eslint-disable-next-line func-names // eslint-disable-next-line func-names
return function () { return /** @type {* & T} */ (
// eslint-disable-next-line prefer-rest-params function memoizedFn() {
const args = [...arguments]; // eslint-disable-next-line prefer-rest-params
const cachableArgs = !serializeObjects ? args : args.map(createCachableArg); const args = [...arguments];
// Allow disabling of cache for testing purposes const cachableArgs = !serializeObjects ? args : args.map(createCachableArg);
// @ts-ignore // Allow disabling of cache for testing purposes
if (!memoizeConfig.isCacheDisabled && cachableArgs in storage) { // @ts-expect-error
// @ts-ignore if (shouldCache && cachableArgs in storage) {
return storage[cachableArgs]; // @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;
},
});