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
@ -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;
},
});