Получение событий при обновлениях IndexedDB с другой вкладки

#javascript #events #indexeddb

#javascript #Мероприятия #indexeddb

Вопрос:

Если у меня IndexedDB база данных открыта на нескольких вкладках, могу ли я отслеживать изменения данных на всех вкладках без перезагрузки?

Комментарии:

1. Связь между вкладками осуществляется через localStorage

2. Нет способа с IndexedDB?

3. Я не знаком с IndexedDB. В этом может быть что-то, что это делает.

Ответ №1:

Чтобы расширить то, что ответил dumbmatter, вот как я добился этого с помощью BroadcastChannel. Если вам нужна дополнительная поддержка, я предлагаю использовать postMessage вместо BroadcastChannel.

 function putThing(db, channel, thing) {
  return new Promise(function(resolve, reject) {
    const transaction = db.transaction('things', 'readwrite');
    transaction.oncomplete = function(event) {
      const message = {operation: 'updated', id: thing.id};
      channel.postMessage(message);
      resolve();
    };
    transaction.onerror = function(event) {
      reject(event.target.error);
    };

    const store = transaction.objectStore('things');
    store.put(thing);
  });
}

// In tab where operation occurs
const db = await open(...);
const channel = new BroadcastChannel('myChannel');
await putThing(db, channel, thing);
channel.close();
db.close();

// In other tab where you want observation of changes
const channel = new BroadcastChannel('myChannel');
channel.onmessage = function(event) {
  const message = event.data;
  console.log('A message occurred', message);
};

  

Несколько моментов:

  • канал не может транслировать сам себе, поэтому его собственная функция прослушивания onmessage с той же вкладкой не получит свои сообщения. Однако вы можете создать несколько экземпляров канала с одинаковым именем канала на одной вкладке, и каждый из них получит сообщения других, если вам понадобится эта функциональность.
  • каналы должны быть недолговечными, поэтому закройте канал, когда закончите. однако это также может быть случай, когда вы хотите, чтобы канал оставался открытым до тех пор, пока открыта страница
  • сообщения канала имеют те же ограничения, что и при хранении объектов в БД, например, вы можете передавать только такие данные, как простые значения свойств, а не функции или экземпляры пользовательских объектов

Комментарии:

1. Как мы можем использовать postMessage, если мы не знаем targetWindow ?

2. @Srikan эта проблема легко решается с помощью BroadcastChannel вместо postMessage, потому что широковещательный канал отправляет его во все окна, и любые окна, которые прослушивают, могут реагировать.

Ответ №2:

Нет встроенного способа сделать это только с помощью IndexedDB. В основном у вас есть два варианта:

  1. Опрашивайте IndexedDB с некоторой частотой и проверяйте наличие новых значений

  2. Используйте какой-либо другой способ взаимодействия между вкладками, чтобы отправить сигнал о том, что вам нужно проверить наличие новых значений из IndexedDB. Например, localStorage (генерирует события перекрестных вкладок, когда что-то меняется) или BroadcastChannel (предназначен именно для обмена данными между вкладками, но не имеет идеальной кросс-браузерной поддержки).