Жизненный цикл кастомного хранилища

Idb-keyval — это минималистичная библиотека для работы с IndexedDB, предоставляющая удобный интерфейс для хранения ключ–значение без необходимости напрямую писать сложные транзакции и обработчики событий. Жизненный цикл кастомного хранилища в idb-keyval строится вокруг понятия Store, который определяет конкретную базу данных и объектное хранилище внутри неё.


Создание кастомного хранилища

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

import { Store } from 'idb-keyval';

const myStore = new Store('my-database', 'my-store');
  • my-database — имя базы данных в IndexedDB. Если база данных не существует, она будет создана автоматически.
  • my-store — имя объектного хранилища (object store). Если хранилище не существует, оно создается при первом обращении.

Создание кастомного хранилища не требует явного открытия соединения с IndexedDB: библиотека выполняет это автоматически при первом вызове операций чтения или записи.


Жизненный цикл хранилища

Жизненный цикл хранилища можно разделить на несколько этапов:

  1. Инициализация

    • При создании экземпляра Store библиотека проверяет наличие базы данных и объектного хранилища.
    • Если база данных существует, проверяется версия и структура хранилища.
    • Если базы данных или хранилища нет, они создаются автоматически через indexedDB.open().
  2. Открытие соединения

    • Фактическое соединение с IndexedDB открывается при первом запросе get, set, del или clear.
    • Соединение сохраняется в фоне для повторного использования в последующих операциях, что оптимизирует производительность.
  3. Чтение и запись данных

    • Методы set, get, del и clear взаимодействуют с объектным хранилищем.
    • set(key, value, store) — добавление или обновление записи.
    • get(key, store) — получение значения по ключу.
    • del(key, store) — удаление записи по ключу.
    • clear(store) — очистка всего хранилища.

Пример записи и чтения данных в кастомном хранилище:

import { set, get } from 'idb-keyval';

await set('username', 'alice', myStore);
const username = await get('username', myStore); // 'alice'

Управление версиями базы данных

При изменении структуры хранилища (например, добавление новых ключей, изменение типов значений) важно учитывать версионность IndexedDB:

const myStoreV2 = new Store('my-database', 'my-store', { version: 2 });
  • Параметр version указывает версию базы данных.
  • При увеличении версии выполняется upgrade через onupgradeneeded, где можно изменить структуру объекта хранилища.
  • idb-keyval автоматически управляет этой частью, упрощая работу с версиями без прямого использования API IndexedDB.

Очистка и закрытие хранилища

Хотя idb-keyval не предоставляет явного метода закрытия соединения, управление жизненным циклом включает:

  • Очистку хранилища: clear(myStore) удаляет все данные.
  • Удаление базы данных:
import { deleteDB } from 'idb';

await deleteDB('my-database');

Удаление базы данных завершает жизненный цикл кастомного хранилища полностью, освобождая ресурсы и позволяя создать новую версию базы данных при следующем обращении.


Использование промисов и асинхронная обработка

Все операции в idb-keyval возвращают промисы, что обеспечивает безопасное асинхронное выполнение:

set('theme', 'dark', myStore)
  .then(() => console.log('Theme saved'))
  .catch(err => console.error('Error saving theme', err));
  • Любая операция, связанная с кастомным хранилищем, может быть обернута в async/await для упрощения кода.
  • Промисы обеспечивают правильное управление состоянием соединения и корректное завершение операций чтения/записи.

Продвинутые возможности кастомного хранилища

  1. Использование нескольких хранилищ в одной базе

    • Можно создать несколько Store с разными именами для логического разделения данных:
const settingsStore = new Store('app-db', 'settings');
const cacheStore = new Store('app-db', 'cache');
  1. Сериализация данных

    • Значения автоматически сериализуются через structuredClone, поддерживая объекты, массивы, даты, Map и Set.
    • При необходимости можно использовать пользовательскую сериализацию, оборачивая set и get.
  2. Оптимизация производительности

    • Повторные вызовы операций используют уже открытое соединение.
    • Асинхронная обработка минимизирует блокировки UI при работе с большими объёмами данных.

Типичные сценарии использования кастомного хранилища

  • Локальное сохранение настроек пользователя: тема, язык, состояние интерфейса.
  • Кеширование данных API: временное хранение JSON-ответов для уменьшения сетевых запросов.
  • Сохранение прогресса в приложениях: игры, редакторы документов или форм, которые работают оффлайн.

Основные методы работы с кастомным хранилищем

Метод Описание Пример
set(key, value, store) Сохранение или обновление значения await set('token', 'abc123', myStore)
get(key, store) Получение значения по ключу const token = await get('token', myStore)
del(key, store) Удаление записи по ключу await del('token', myStore)
clear(store) Очистка всех данных хранилища await clear(myStore)

Эти методы являются основой для управления жизненным циклом кастомного хранилища, обеспечивая простое и безопасное взаимодействие с IndexedDB через idb-keyval.