#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. В основном у вас есть два варианта:
-
Опрашивайте IndexedDB с некоторой частотой и проверяйте наличие новых значений
-
Используйте какой-либо другой способ взаимодействия между вкладками, чтобы отправить сигнал о том, что вам нужно проверить наличие новых значений из IndexedDB. Например, localStorage (генерирует события перекрестных вкладок, когда что-то меняется) или BroadcastChannel (предназначен именно для обмена данными между вкладками, но не имеет идеальной кросс-браузерной поддержки).