Troll the Legacy
Troll the Legacy

Reputation: 715

Getting events on IndexedDB updates from another tab

If I have IndexedDB database opened in multiple tabs, can I track data changes on all tabs without reloading?

Upvotes: 4

Views: 2975

Answers (2)

Josh
Josh

Reputation: 18690

To extend what dumbmatter answered, here is how I achieved it with BroadcastChannel. If you are going for more support I suggest using postMessage instead of a 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);
};

A few points:

  • channel cannot broadcast to itself, so its own same-tab onmessage listener function will not get its messages. However, you can create multiple channel instances with the same channel name all on the same tab and each one will get the others' messages should you need that functionality.
  • channels should be short lived, so close the channel when done. however, this could also be a case where you want the channel to stay open for as long as the page is open
  • channel messages follow similar limitations as storing objects in db, e.g. you can only pass around data like simple property values, not functions or custom object instances

Upvotes: 4

dumbmatter
dumbmatter

Reputation: 9673

There's no built in way to do this with IndexedDB alone. You basically have two options:

  1. Poll IndexedDB with some frequency and check for new values

  2. Use some other way of cross-tab communication to send a signal that you need to check for new values from IndexedDB. For example localStorage (emits cross-tab events when something changes) or a BroadcastChannel (designed exactly for the purpose of cross-tab communication, but does not have perfect cross browser support).

Upvotes: 4

Related Questions