Как стать автором
Обновить

Комментарии 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 и не нужен вовсе.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории