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} */ (
function memoizedFn() {
// eslint-disable-next-line prefer-rest-params // eslint-disable-next-line prefer-rest-params
const args = [...arguments]; const args = [...arguments];
const cachableArgs = !serializeObjects ? args : args.map(createCachableArg); const cachableArgs = !serializeObjects ? args : args.map(createCachableArg);
// Allow disabling of cache for testing purposes // Allow disabling of cache for testing purposes
// @ts-ignore // @ts-expect-error
if (!memoizeConfig.isCacheDisabled && cachableArgs in storage) { if (shouldCache && cachableArgs in storage) {
// @ts-ignore // @ts-expect-error
return storage[cachableArgs]; return storage[cachableArgs];
} }
// @ts-ignore // @ts-expect-error
const outcome = functionToMemoize.apply(this, args); const outcome = functionToMemoize.apply(this, args);
// @ts-ignore // @ts-expect-error
// eslint-disable-next-line no-param-reassign // eslint-disable-next-line no-param-reassign
storage[cachableArgs] = outcome; storage[cachableArgs] = outcome;
return 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;
},
});