Комментарии 15
Интересная статья, отложу и почитаю
Неплохо. Спасибо за статью.
А если рекурсия? То есть функция запросит мемоизированное значение прямо или опосредованно? Вполне себе вариант в сложных случаях отложенных вычислений
Этот вопрос возник до прочтения секции "Мемоизация рекурсивных функций" или после? Если сделать как в примере в этой секции, то не меомоизированной версии функции не будет. Будет только мемоизированая версия и вызываться всегда будет только она
К своему стыду, упустил этот раздел.
Но, после прочтения, вопрос всё-же остался.
Что если рекурсивное обращение произошло до того, как результат попал в кеш?
Я не уверен, что понимаю вопрос. Поверхностно всё просто, результат есть в кэше - берём оттуда, функцию не вызываем. Нет кеша - вызываем функцию и записываем в кэш. Даже при отложенных вычислениях мы Сразу кладём в кэш промис
Попробуй написать маленький пример рекурсивной функции и поставь в нём console.log'и. Если так всё равное не разберёшься. То скинь пример своей функции сюда - попробую помочь
Утрирую:
const getValue1 = withMemo(() => getValue2() - 1);
const getValue2 = withMemo(() => getValue1() + 1);
getValue1(); // Бесконечная рекурсия.
В случае с промисами будет не бесконечная рекурсия с ошибкой, а бесконечное ожидание, что ещё хуже.
Я о том, вообще-то, что для разрешения таких ситуаций тоже можно придумывать различные стратегии.
Ещё проще, чтобы стала понятна проблема:
const getValue = withMemo(() => getValue());
Вычисленное значение попадает в кеш, очевидно, только после того, как завершится вычисление. Но рекурсивный вызов происходит во время вычисления. То есть значения в кеше ещё нет. Значит вызов произойдёт снова, и снова, и снова...
Оба примера в принципе нерабочие. Мемоизация тут не при чём. Такое ощущение, что ты пишешь "можно коряво написать рекурсию и никогда из неё не выйти". Да, можно. Если в твоих примерах убрать withMemo
, то будет просто сломанная рекурсия
Это утрированные примеры, да. Тем не менее, вполне себе реально получить ситуацию.
А стратегия выходя из неё может проистекать из условий задачи. Например, можно ведь возвращаеть значение по умолчанию, пока результат вычисляется:
const getValue = withMemo(
async () => ({ done: true, value: await someVeryLongOperation() }),
{ defaultValue: { done: false, value: undefined } },
);
Для рекурсии можно сделать такую нашлепку поверх withMemo
:
const recMemo = (f) => {
let memFunc;
const func = (...a) => memFunc(...a);
memFunc = withMemo(f(func));
return memFunc;
};
// пример использования
// функция Фибоначчи в длинной арифметике
const memFib = recMemo(
(func) => (x) => x < 2n ? x : func(x - 1n) + func(x - 2n)
);
memFib(200n); // 280571172992510140037611932413038677189525n
Этот вариант позволяет создать функцию "на лету" и сразу передать куда-нибудь, не сохраняя в переменную.
очень интересная статья, интересно было бы продолжить эту тему в контексте подобия react-query
очень интересная статья, интересно было бы продолжить эту тему в контексте подобия react-query
Если не делать запросы из разметки (view-слоя) как написано
если две части приложения (хедер и сайдбар) одновременно запрашивают getCurrentUser, то на сервер уйдёт 2 одинаковых запроса
то судя по всему react-query и не нужен вовсе.
Реализация мемоизации в JavaScript