Мемоизация с TTL сохраняет результат вместе со временем истечения и ключом аргументов. После истечения срока функция вычисляется снова; правила сравнения аргументов нужно задать явно.
Создание функции мемоизации
Мемоизация с TTL сохраняет результат вместе со временем истечения и ключом аргументов. После истечения срока функция вычисляется снова; правила сравнения аргументов нужно задать явно.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Разработать функцию memoize, принимающую два аргумента: целевую функцию, которую следует мемоизировать, и длительность (время), в течение которой результат этой функции будет храниться в кэше.
Ответ
Мемоизация с TTL сохраняет результат вместе со временем истечения и ключом аргументов. После истечения срока функция вычисляется снова; правила сравнения аргументов нужно задать явно.
function memoize(fn, ttl) {
if (!Number.isFinite(ttl) || ttl < 0) throw new RangeError('Некорректный TTL');
let entries = [];
return function (...args) {
const now = performance.now();
entries = entries.filter(entry => entry.until > now);
const hit = entries.find(entry => entry.context === this &&
entry.args.length === args.length && entry.args.every((value, i) => Object.is(value, args[i])));
if (hit) return hit.value;
const value = fn.apply(this, args);
entries.push({ context: this, args, value, until: performance.now() + ttl });
return value;
};
}
TTL задан в миллисекундах, отсчитывается после синхронного вычисления. Примитивы сравниваются по Object.is, объекты — по ссылке; this входит в ключ. Это вариант для синхронных чистых функций: Promise и очистка rejected-результатов требуют отдельной политики. Поиск линейный по числу записей, просроченные записи очищаются при следующем вызове; для большого кэша нужен лимит размера.