localForage — Что делать если localStorage уже не хватает?

1bbce18ee7918c90a9cd3fba4dd1c2c8.png

Как вы уже, наверное, знаете, браузерные хранилища данных, такие как localStorage и sessionStorage, сильно ограничены в своих размерах и для хранения большого количества данных не подходят. В разных браузерах этот размер варьируется, но в среднем принято считать, что это около 5 МБ.

Что же делать, если нужно больше? Для этой ситуации в браузере предусмотрен другой Web API — IndexedDB. Его размеры и регулирование также сильно варьируются от браузера к браузеру, но обычно это около 50% доступного дискового пространства на устройстве пользователя.

Сам этот API достаточно неудобен в использовании, так как предполагает работу с большим количеством объёмных конструкций в коде и без использования заранее подготовленных собственных утилит не представляется возможным.

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

  1. Dexie.js

  2. idb

  3. localForage

Нас больше интересует последний вариант — localForage. Он в отличие от остальных библиотек реализует API очень близкий по реализации localStorage, что ещё больше упрощает работу для решения большинства задач.

Перед тем как мы перейдём к его подробному разбору, хотелось бы дополнительно отметить несколько дополнительных преимуществ перед стандартным localStorage, помимо увеличенного размера хранилища:

  1. Асинхронный API — при частых операциях с данными наш поток не будет забиваться как в случае с localStorage, все задачи выполняются отложено.

  2. Формат хранения данных — localForage поддерживает любой формат данных (объекты, массивы, бинарные данные и так далее) и не требует предварительной сериализации / десериализации данных, так как под капотом работает IndexedDB, который умеет это делать из коробки. Это удобно и не требует дополнительных вычислительных трат на преобразование.

Итак, приступим к разбору.

Установка

# Eсли у вас npm
npm install localforage

# Если у вас yarn
yarn add localforage

Также можно создать глобальную переменную при помощи ручной установки тега script в коде:


Основные методы

Библиотека предлагает 2 варианта обработки операций: при помощи колбэков и при помощи промисов. Далее на примере метода getItem можно будет увидеть их оба.

getItem

getItem(key, callback)

Получает содержимое хранилища по ключу key и передаёт его в callback.

Если ранее был сохранён undefined по определённому ключу, то при получении этого элемента при помощи getItem () будет возвращён null. Это сделано по причинам совместимости localForage и ограничений localStorage.

localforage.getItem('somekey').then((value) => {
    console.log(value);
});
localforage.getItem('somekey', (error, value) => {
    console.log(value);
});

setItem

setItem(key, value, callback)  

Сохраняет данные value по заданному ключу key и вызывает callback.

localforage.setItem('somekey', 'some value').then((value) => {
    console.log(value);
});

removeItem

removeItem(key, callback)

Удаляет данные по ключу key и вызывает callback.

localforage.removeItem('somekey').then(() => {
    console.log('Ключ somekey был успешно удалён.');
});

clear

clear(callback)

Удаляет все ключи из базы данных.

localforage.clear().then(() => {
    console.log('База данных была очищена.');
});

length

length(callback)

Возвращает количество записей в хранилище и вызывает callback.

localforage.length().then((numberOfKeys) => {
    console.log(numberOfKeys);
});

key

key(keyIndex, callback)

Получает имя ключа по его индексу (порядковому номеру) и передаёт его в callback.

localforage.key(2).then((keyName) => {
    console.log(keyName);
});

keys

keys(callback)

Возвращает список всех ключей хранилища и передаёт их в callback.

localforage.keys().then((keys) => {
    console.log(keys);
});

iterate

iterate(iteratorCallback, callback)

Проходит по всем элементам в хранилище используя функцию iteratorCallback и возвращает результат в callback.

localforage.iterate((value, key, iterationNumber) => {
    console.log([key, value]);
});

Драйверы

Под драйверами в библиотеке подразумеваются типы хранилищ, используемых для записи данных. По-умолчанию их 3: IndexedDB, WebSQL (устарел и не рекомендуется к использованию) и localStorage. Если явно не указать необходимый драйвер, то localForage автоматически его выберет на основании поддержки браузером того или иного API в следующем порядке:

  1. IndexedDB

  2. WebSQL

  3. localStorage

Мы можем управлять этим поведением при помощи метода setDriver.

setDriver(driverName)
setDriver([driverName, nextDriverName])
// Устанавливаем один предпочтительный драйвер
localforage.setDriver(localforage.LOCALSTORAGE);

// Устанавливаем несколько драйверов на случай, если один или несколько из них не будут поддерживаться в браузере
localforage.setDriver([localforage.WEBSQL, localforage.INDEXEDDB]);

Также при помощи метода defineDriver мы можем объявлять свои собственные драйверы.

Конфигурация

Каждому хранилищу, создаваемому при помощи localForage можно задавать определённые настройки при помощи конфигурации.

localforage.config({
    driver: localforage.INDEXEDDB, // Указывает, какой драйвер использовать. Может быть: localforage.LOCALSTORAGE, localforage.INDEXEDDB или localforage.WEBSQL
    name: 'myApp', // Имя базы данных (используется для идентификации хранилища)
    version: 1.0, // Версия базы данных
    description: 'My App storage', // Описание базы данных
    size: 4980736, // Размер хранилища в байтах для WebSQL (по умолчанию — 5MB)
});

Несколько хранилищ

Для работы сразу с несколькими хранилищами сразу мы можем использовать методы:

  1. createInstance — для создания нового инстанса

  2. dropInstance — для удаления существующего

// Создаем первый инстанс с уникальным именем 'userData'
const userDataStore = localforage.createInstance({
    name: 'myApp',
    storeName: 'userData',
    driver: localforage.INDEXEDDB,
});

// Записываем в него какие-то данные
userDataStore.setItem('username', 'Вася').then(() => {
    console.log('Данные пользователя сохранены');
});


// Создаем второй инстанс с уникальным именем 'appSettings'
const appSettingsStore = localforage.createInstance({
    name: 'myApp',
    storeName: 'appSettings', 
    driver: localforage.LOCALSTORAGE, 
});

// Также записываем в него какие-то данные
appSettingsStore.setItem('theme', 'dark').then(() => {
    console.log('Настройки приложения сохранены.');
});


// Удаляем их оба
userDataStore.dropInstance().then(() => {
  console.log('userDataStore был удалён')
});

appSettingsStore.dropInstance().then(() => {
  console.log('appSettingsStore был удалён')
});

Дополнительно

Думаю на данном этапе у вас уже сложилась картина как устроена библиотека. Методы, которые я не перечислил здесь, вы можете самостоятельно найти в официальной документации.

© Habrahabr.ru