@proscom/prostore-local-storage v0.2.12
prostore-local-storage
Адаптер для связи между внешними хранилищами (например, localStorage) и prostore.
В библиотеке представлено несколько классов:
- Класс стора
WebStorageValueStore, стейт которого синхронизирован сlocalStorage(илиsessionStorage). - Более абстрактный вариант
StorageValueStoreдля связи с произвольным внешним хранилищем через адаптер. - Адаптер для
localStorage:WebStorageAdapter(StorageValueStore + WebStorageAdapter = WebStorageValueStore) - Класс стора
LocalStorageStoreдля синхронизации сразу нескольких ключей сlocalStorage.
Подписка на изменение значений localStorage / sessionStorage происходит
через браузерное событие storage.
Значения автоматически сериализуются в JSON при записи и парсятся при чтении.
WebStorageValueStore
Используйте WebStorageValueStore, чтобы синхронизировать значение с localStorage.
Инстанциируйте класс, передав в него инстанс localStorage, имя ключа и трансформер значения.
Трансформер принимает значение после парсинга из формата JSON.
Его можно использовать для обработки некорректных значений.
Например, если требуется определенная структура объекта в localStorage, то в функции парсинга можно
проверить имеющийся объект и вернуть null, если он некорректный.
import { WebStorageValueStore } from '@proscom/prostore-local-storage';
const LOCAL_STORAGE_KEY_SCORE = 'score';
// Синхронизированный стор
const scoreStore = new WebStorageValueStore<number>(
localStorage,
LOCAL_STORAGE_KEY_SCORE,
// Трансформер значения. Так как внешнее хранилище может изменяться извне,
// то нет гарантии что значение имеет определенный тип.
// С помощью трансформера можно привести значение к нужному типу
(value) => +value || 0
);
// Регистрируем обработчик события storage
scoreStore.registerListener();
// При изменении значения во внешнем хранилище, оно изменится и в сторе.
// Подписываемся на изменение значения как на любой обзервабл
const sub = scoreStore.state$.subscribe((score) => {
// После первоначальной загрузки данных из внешнего хранилища loaded=true
// score.value содержит непосредственно значение
console.log(score.loaded, score.value);
});
// Значение стора можно изменить, тогда оно меняется и во внешнем хранилище
scoreStore.setValue(5);
// Отписаться от обновлений стора можно так
sub.unsubscribe();
// Перед удалением scoreStore обработчик событий надо снять
scoreStore.destroy();StorageValueStore
Класс StorageValueStore - это более абстрактная версия WebStorageValueStore,
которая может работать с любым внешним хранилищем.
Для её использования необходимо реализовать адаптер доступа к значению,
удовлетворяющий интерфейсу IStorageValueAdapter:
export interface IStorageValueAdapter<T> {
// Обзервабл значения во внешнем хранилище
// При подписке он должен выдавать текущее значение (синхронно или асинхронно)
value$: Observable<T | null>;
// Функция для изменения значения во внешнем хранилище
setValue(value: T | null): void;
}В библиотеке представлен адаптер WebStorageAdapter для работы с localStorage и sessionStorage.
Ниже представлен пример создания собственного адаптера:
import {
StorageValueStore,
IStorageValueAdapter
} from '@proscom/prostore-local-storage';
import { BehaviorSubject } from 'rxjs';
// Бесполезный адаптер, который вместо внешнего хранилища сохраняет значение в BehaviorSubject
class MyAdapter<T> implements IStorageValueAdapter<T> {
value$ = new BehaviorSubject<T | null>();
setValue(value: T | null) {
this.value$.next(value);
}
}
// Создаём StorageValueStore используя собственный адаптер
const myStore = new StorageValueStore<string>(new MyAdapter<string>(), (x) =>
String(x)
);WebStorageAdapter
Адаптер для связи StorageValueStore с localStorage и sessionStorage.
В большинстве случаев вместо него следует использовать WebStorageValueStore.
import {
StorageValueStore,
WebStorageAdapter
} from '@proscom/prostore-local-storage';
const adapter = new WebStorageAdapter(localStorage, 'test');
const sub = adapter.value$.subscribe((value) => console.log(value));
adapter.setValue('newValue');
sub.unsubscribe();
const store = new StorageValueStore(adapter);LocalStorageStore
@deprecated - рекомендуется использовать несколько WebStorageValueStore вместо одного LocalStorageStore.
Чтобы использовать LocalStorageStore, просто инстанциируйте его, передав массив строк-ключей, значения которых необходимо прочитать и отслеживать.
const LOCAL_STORAGE_KEY_ACCESS_TOKEN = 'accessToken';
const localStorageStore = new LocalStorageStore(localStorage, [
LOCAL_STORAGE_KEY_ACCESS_TOKEN
]);
// Вызов этой функции необходим для подписки на изменения
// Можно ее не вызывать, тогда значения будут прочитаны только один раз
localStorageStore.registerListener();Теперь можно подписаться на все данные сразу:
localStorageStore.state$.subscribe((state) => {
/*
* state = {
* accessToken: 'myAccessToken'
* }
*/
});Или только на конкретный ключ:
localStorageStore.get$(LOCAL_STORAGE_KEY_ACCESS_TOKEN).subscribe((state) => {
// state = 'myAccessToken'
});Если требуется подписаться на несколько ключей, то можно использовать combineLatest:
combineLatest(
localStorageStore.get$(LOCAL_STORAGE_KEY_ACCESS_TOKEN),
localStorageStore.get$(LOCAL_STORAGE_KEY_REFRESH_TOKEN)
).subscribe(([accessToken, refreshToken]) => {
// ...
});Чтобы записать значение в стор и в localStorage, можно воспользоваться методом setItem:
localStorageStore.setItem(LOCAL_STORAGE_KEY_ACCESS_TOKEN, 'differentToken');Чтобы получить текущее значение ключа без подписки, можно обратиться к состоянию стора:
console.log(localStorageStore.state[LOCAL_STORAGE_KEY_ACCESS_TOKEN]);Сериализация в JSON
LocalStorageStore и WebStorageValueStore автоматически сериализуют все переданные значения в JSON при записи и пытаются парсить JSON при чтении:
const LOCAL_STORAGE_KEY_DATA = 'data';
localStorageStore.setItem(LOCAL_STORAGE_KEY_DATA, { data: 2 });
// В data запишется строка: '{ "data": 2 }'Если значение в localStorage не является валидным JSON, то LocalStorageStore и WebStorageValueStore возвращают null.