Сбор мусора в магазинах Redux/Flux

Я работаю над проектом, в котором мы в настоящее время используем Redux для управления состоянием в нашем одностраничном приложении на основе React, и мы столкнулись с проблемой, касающейся того, когда и как очищать неиспользуемые данные из наших хранилищ (технически подсостояние в глобальном магазине Redux).

Например, у нас есть "магазин" календаря, который выглядит

calendar = {
    "2015-11-06": {
        // Loads of data
    },
    ... // More dates
}

В основном мы заботимся только об одной дате в данный момент времени, но бывают случаи, когда существуют разные компоненты, которым одновременно требуются разные даты календаря.

Вопрос в следующем: есть ли какая-то стратегия по "сборке мусора" магазинов?

Моя первоначальная мысль заключалась в том, что компоненты, которым нужна конкретная календарная дата, должны будут «зарезервировать» эту дату, и когда она будет размонтирована, она удалит свое резервирование. Таким образом, когда мы достигаем какого-то ограничения по размеру, мы можем просто удалить все даты, которые не зарезервированы каким-либо компонентом.

Однако это немного хлопотно, поскольку добавляет необходимость в компонентах для обработки «резервирования» при получении даты и при размонтировании компонента.

Является ли это осуществимой стратегией или есть лучшая альтернатива?


person Markus-ipse    schedule 06.11.2015    source источник
comment
Итак, если кто-то переключается между двумя календарными датами, вы перезагружаете данные для этой даты? Возможно, вы захотите оценить, действительно ли вы храните достаточно данных на клиенте, чтобы повлиять на производительность. Другая стратегия состоит в том, чтобы сохранить массив активных дат (строковых ключей), и сделать так, чтобы ваш редуктор строил только большой объект с ключами, соответствующими датам в массиве.   -  person pfkurtz    schedule 17.03.2016


Ответы (2)


Похоже на хороший пример использования WeakSet или WeakMap.

WeakMap слабо хранит ссылки на свои ключи, а это означает, что если нет других ссылок на один из его ключей, объект подлежит сборке мусора.

person Dominic    schedule 06.11.2015
comment
Звучит очень интересно, но мы используем бесшовное неизменяемое для нашего состояния, например. в наших редьюсерах, и он не поддерживает слабые наборы/карты AFAIK :( - person Markus-ipse; 06.11.2015
comment
Я знаю, что это было опубликовано уже давно, но для тех, кто найдет это: вы не должны использовать WeakMap для вещей, помеченных строками (или числами и т. д.). Строка никогда не будет очищена, поэтому WeakMap не будет освобождать память, когда что-то больше не используется. Почему? Потому что WeakMap освобождает память, если ссылка на запись полностью исчезла. Если вы назначите ключ, например let key = 'myKey';, а затем удалите ключ key = null;, вы все равно сможете переназначить его key = 'myKey', и он будет соответствовать ссылке. - person Dracco; 18.01.2019
comment
Хороший вопрос, и этот ответ довольно старый, я думаю, что в то время я меньше знал о Redux, что, я думаю, не подходит для WeakSet/Map. Пользователь должен запускать действия, необходимые для очистки данных хранилища. - person Dominic; 18.01.2019

Ключ ко всему этому лежит в комбинации этого утверждения:

В основном мы заботимся только об одной дате в данный момент времени, но бывают случаи, когда существуют разные компоненты, которым одновременно требуются разные даты календаря.

...и как мы думаем о состоянии в такой архитектуре, как Flux/Redux.

Ничто не мешает вам реструктурировать существующее хранилище данных следующим образом:

calendar = {
    mainDate: {
        date: "2015-11-06",
        // Loads of data
    }
}

Затем, всякий раз, когда вы сталкиваетесь с одним из тех особых случаев, когда вам нужно более одной даты, вы выполняете действие, которое заменяет состояние calendar чем-то вроде этого:

calendar = {
    mainDate: {
        date: "2015-11-06",
        // Loads of data
    },
    otherDate: {
        date: "2016-02-29",
        // Other data. Perhaps even less than the loads you'd have in mainDate
    }
}

В какой-то момент ваши компоненты сами решат, нужно ли им смотреть на mainDate или otherDate. (Они вполне могут извлечь соответствующий компонент, а затем передать его содержимое своим дочерним компонентам; возможно, вы захотите ввести здесь уровень абстракции.)

И когда другой компонент будет выполнен с использованием другой даты, он вызовет другое действие, которое генерирует:

calendar = {
    mainDate: {
        date: "2015-11-06",
        // Loads of data
    }
}

... таким образом автоматически заботясь о сборе мусора.

Очевидно, что здесь нужно проработать много деталей реализации, но это зависит от вашей ситуации. Ключевая концепция заключается в том, чтобы содержать все состояния (и только состояния), необходимые для запуска приложения в любой момент времени, и использовать действия для перехода из одного состояния в другое.

person Craig Walker    schedule 11.04.2016