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
|
* @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;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue