Совместное использование хранилища между вкладками

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


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

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

Особенности поведения:

  • Асинхронность операций: все методы get, set, del и clear возвращают Promise. Это позволяет корректно работать с несколькими вкладками, не блокируя интерфейс.
  • Транзакции: IndexedDB использует транзакции для гарантии целостности данных. Когда одна вкладка выполняет set, другие вкладки получают доступ к новым данным только после завершения транзакции.
  • Кэширование: некоторые браузеры могут кэшировать данные, поэтому события синхронизации между вкладками могут иметь небольшую задержку.

Методы idb-keyval для совместного использования

Базовый набор методов остаётся стандартным:

import { get, set, del, clear, keys, upd ate } from 'idb-keyval';

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

Сохранение данных:

await se t('userSettings', { theme: 'dark', fontSize: 16 });

Получение данных из другой вкладки:

const settings = await get('userSettings');
console.log(settings); // { theme: 'dark', fontSize: 16 }

Обновление данных с учётом текущего состояния:

await upd ate('userSettings', old => ({ ...old, fontSize: 18 }));

Удаление и очистка:

await del('userSettings');
await clear();

События синхронизации между вкладками

Для реактивного обновления интерфейса при изменении данных в других вкладках используют BroadcastChannel или событие storage для простых случаев:

const channel = new BroadcastChannel('idb-keyval-sync');

channel.onmess age = (event) => {
    console.log('Данные изменены в другой вкладке:', event.data);
};

// Отправка события после изменения данных
await se t('userSettings', { theme: 'light' });
channel.postMessage({ key: 'userSettings', value: { theme: 'light' } });

Особенности:

  • BroadcastChannel работает только между вкладками одного происхождения (origin).
  • Для старых браузеров можно использовать комбинацию localStorage + событие storage:
localStorage.setItem('userSettings', JSON.stringify({ theme: 'light' }));
window.addEventListener('storage', (event) => {
    if (event.key === 'userSettings') {
        console.log('Обновлено значение:', JSON.parse(event.newValue));
    }
});

Практические рекомендации

  1. Использовать отдельный канал для синхронизации Для разных категорий данных рекомендуется создавать отдельные BroadcastChannel, чтобы избежать лишнего трафика сообщений.

  2. Обновление состояния интерфейса Любые изменения, приходящие из других вкладок, должны аккуратно обрабатываться. Необходимо проверять текущий статус компонента перед применением изменений, чтобы избежать конфликтов.

  3. Минимизировать количество операций записи Частые вызовы set создают нагрузку на IndexedDB и могут вызывать задержки при синхронизации. Для больших объектов лучше использовать батчи или update.

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


Архитектурные сценарии

  • Совместное редактирование форм: несколько вкладок с одной и той же формой могут синхронизировать введённые данные в реальном времени.
  • Кэширование и состояние приложения: приложения с большим количеством состояния могут хранить его в IndexedDB и синхронизировать между вкладками, избегая загрузки с сервера.
  • Уведомления об обновлениях: если одно окно обновляет контент, остальные получают уведомление и могут автоматически перерендерить интерфейс.

Заключение по синхронизации

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