В посте Сохранение состояния в JavaScript - wora / cache-persist - Начало работы я покажу вам, как родился wora / cache-persist и как легко его использовать в ваших приложениях.
Сегодня я хочу рассказать вам с помощью исходного кода, как Cache использует состояние и как он управляет обменом данными (чтение / запись данных) с хранилищем, обеспечивающим высокая эффективность.
Чтение данных
Чтение данных полностью управляется объектом Кэш с помощью поля data, простого JavaScript Object и его синхронного функции чтения.
Это означает, что приложение считывает всю информацию с той же производительностью, что и простой кэш в памяти!
Запись данных
Данные записываются за два момента: первый, выполняется только один раз, когда кеш должен быть инициализирован, а второй когда приложение использует функции записи, предоставляемые кешем.
Посылка
Чтобы решить проблему записи данных, необходимо создать предпосылку для некоторых внутренних объектов и концепций библиотеки: StorageProxy, хранилище и мутации
- StorageProxy
StorageProxy - это внутренний объект библиотеки, задача которого - сделать взаимодействие с хранилищем прозрачным для пользователей. Он реализует интерфейс IStorageHelper.
- Хранилище
Хранилище - это внутренний объект библиотеки, который уважает этот интерфейс таким образом, чтобы скрыть сложность и специфику используемого реального хранилища:
В настоящее время реализовано хранилище для localStorage, sessionStorage, AsyncStorage и indexedDB. Если необходимо использовать другое хранилище, просто создайте объект, реализующий интерфейс ICacheStorage, и настройте его в параметре storage
[Необязательно] [По умолчанию: localStorage / AsyncStorage
]
- Мутации
Библиотека позволяет вам настроить, как данные должны быть изменены перед записью / чтением из хранилища, с помощью следующих двух опций:
mutateKeys
: [Необязательно] с помощью этой опции вы можете настроить массив функций мутации, которые будут выполняться для изменения ключей во время записи / чтения в хранилище. Параметр префикс вставит функцию prefixLayer как первую в списке.
mutateValues
: [Необязательно] с помощью этой опции вы можете настроить массив функций мутации, которые будут выполняться для изменения значений во время записи / чтения в хранилище. Параметр сериализации вставит функцию jsonSerialize последней в списке.
Можно реализовать любую другую мутацию, реализовав интерфейсы, описанные ниже:
- Заданная функция будет вызвана перед записью в хранилище.
- Функция get будет вызываться после чтения в хранилище.
В дополнение к функциям jsonSerialize и prefixLayer в библиотеке уже присутствует еще одна функция мутации - filterKeys, которая позволяет вы должны определить функцию, чтобы определить, какие ключи сохраняются.
Ниже мы можем увидеть, как эти два параметра используются StorageProxy для преобразования массива в единую функцию мутации с помощью функции compose:
Что ж, теперь мы готовы посмотреть, как выполняется запись данных в библиотеку .
Инициализация кеша
Инициализация кеша выполняется с помощью функции восстановления, самой важной функции из всех, на самом деле она обязательно должна использоваться для подключения хранилища к его эталонному хранилищу и восстановления состояния кеша.
Его исполнение состоит из:
- promisesRestored используется, чтобы избежать многократного восстановления
- запрос ранее сохраненного состояния у StorageProxy, через его функцию восстановления
- выполнение функции mergeState между постоянным состоянием и данными, уже присутствующими в кэше (обычно initialState).
- если функция mergeState возвращает состояние, отличное от постоянного, состояние заменяется
- если все прошло хорошо, регидратированному полю присвоено значение true, в противном случае выдается ошибка
Как StorageProxy восстанавливает постоянное состояние? Мы можем ответить на этот вопрос, проанализировав исходный код его функции восстановления, и мы можем увидеть, что данные восстанавливаются из хранилища, выполнив следующие действия:
- извлекает все ключи, управляемые магазином, с помощью функции getAllKey
- фильтрует ключи с помощью mutateKey
- Функция хранилища multiGet используется для получения всех отфильтрованных значений ключей (хранилища, которые изначально реализуют multiGet, более эффективны, см. AsyncStorage, поддерживающий реакцию).
- ключи и значения изменяются функциями mutate get
- состояние создается с использованием измененных ключей и значений
Запись через функции, предоставляемые Cache
Как видно из кода кэша, функции записи выполняются в синхронном режиме для изменения состояния (поле data) и уведомления StorageProxy с помощью push функция измененного ключа.
Функция push StorageProxy выполняет четыре простых задачи:
- мутация ключа и
- убедитесь, что это ключ к сохранению
- очередь внутренний ключ
- выполняет функцию debounce
По истечении срока действия дебона (параметры кешированияthrottle
: [Необязательно] [По умолчанию: 500
]) выполняется функция выполнения и переходит к следующему:
- удалить все повторяющиеся ключи из очереди, строка 3
- сгруппировать все ключи, которые необходимо изменить и выполнить изменение значений, строка 32
- group: все ключи будут удалены, строка 34
- если есть ключи, которые нужно удалить, выполняется запрос multiRemove в хранилище (хранилища, которые изначально реализуют multiRemove, более эффективны, см. реакцию родной AsyncStorage), строки 39 и 40
- если есть ключи, которые нужно изменить, выполняется запрос multiSet в хранилище (хранилища, которые изначально реализуют multiSet, более эффективны, см. реакцию родной AsyncStorage), строки 42 и 43
Выводы:
как кэш использует состояние и как он управляет обменом данными с хранилищем, обеспечивая высокую эффективность
Использование состояния как при записи, так и при чтении всегда происходит в синхронном режиме и с использованием внутреннего кеша.
Чтение данных из хранилища выполняется только один раз при запуске приложения и использовании функции multiGet.
Запись данных в хранилище поставлена в очередь, устранена, дубликаты удалены, и только multiSet и multiRemove запросы делаются.
Что дальше
Если вы сопровождаете библиотеку управления состоянием и тоже хотели бы интегрировать i, я предлагаю вам прочитать сообщение о том, как я легко интегрировал его в apollo: Сохранение состояния в JavaScript - wora / cache-persist - Интеграция в кеш apollo
Как вы можете внести свой вклад
- Если вы являетесь создателем библиотеки управления состоянием, рассмотрите возможность интеграции этой библиотеки.
- Поставьте звезду репозиторию и поделитесь ею, вы поможете проекту и людям кому это пригодится
- Создавайте проблемы, ваши вопросы станут ценным подспорьем
- PR приветствуются, но всегда лучше сначала открыть проблему, чтобы помочь мне и другим людям, оценивающим ее