Как idb-keyval открывает и переиспользует соединение

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

Инициализация базы данных

При создании хранилища через idb-keyval не требуется явно открывать соединение с IndexedDB. Библиотека использует объект IDBDatabase, управляя его состоянием внутри.

Пример создания собственного хранилища:

import { Store } from 'idb-keyval';

const myStore = new Store('my-database', 'my-store');
  • my-database – имя базы данных.
  • my-store – имя object store внутри базы.

Если объект store с указанным именем отсутствует, библиотека автоматически создаёт его при первой операции записи или чтения.

Переиспользование соединения

idb-keyval оптимизирует работу с соединением через кэширование экземпляра IDBDatabase.

Механизм работы:

  1. Первый вызов любой операции (get, set, del) инициирует открытие соединения через IndexedDB.
  2. Созданное соединение сохраняется в замыкании библиотеки.
  3. Все последующие операции используют уже открытое соединение.
  4. Соединение закрывается только при явном вызове db.close() или при выгрузке страницы.

Такой подход минимизирует накладные расходы на открытие соединения и повышает производительность при массовых запросах.

Асинхронные операции и транзакции

idb-keyval использует транзакции IndexedDB с режимом readonly или readwrite в зависимости от выполняемой операции.

  • Чтение:
import { get } from 'idb-keyval';

const value = await get('user-settings', myStore);
  • Запись:
import { set } from 'idb-keyval';

await set('user-settings', { theme: 'dark', fontSize: 14 }, myStore);
  • Удаление:
import { del } from 'idb-keyval';

await del('user-settings', myStore);

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

Кэширование соединений в пользовательских хранилищах

Если требуется несколько хранилищ внутри одной базы данных, idb-keyval позволяет создавать несколько экземпляров Store, все они будут переиспользовать одно соединение к одной базе:

const userStore = new Store('my-database', 'users');
const settingsStore = new Store('my-database', 'settings');

Обе переменные используют одно соединение к my-database, но транзакции выполняются в разных object store. Это снижает нагрузку на браузер и предотвращает потенциальные конфликты открытий базы данных.

Контроль версии базы данных

idb-keyval позволяет безопасно обновлять схему базы данных через параметр версии:

const storeV2 = new Store('my-database', 'my-store', { version: 2 });

При увеличении версии выполняется событие upgrade, где можно изменять структуру object store. При этом соединение продолжает переиспользоваться в рамках новой версии, что делает обновления прозрачными для основных операций чтения/записи.

Работа с большим количеством ключей

Переиспользование соединения особенно важно при массовых операциях:

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

await set('key1', 'value1', myStore);
await set('key2', 'value2', myStore);

const values = await getMany(['key1', 'key2'], myStore);

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

Внутреннее управление соединением

Механизм работы библиотеки можно схематически представить так:

  1. Проверка наличия открытого соединения в замыкании.
  2. Если соединение отсутствует → вызывается indexedDB.open.
  3. При успешном открытии соединение сохраняется.
  4. Все операции используют сохранённое соединение.
  5. Закрытие соединения управляется браузером либо вручную через объект IDBDatabase.

Такой подход обеспечивает устойчивость и эффективность при постоянной работе с IndexedDB, предотвращает утечки соединений и снижает вероятность ошибок при параллельных транзакциях.


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