从另一个选项卡获取有关 IndexedDB 更新的事件

Getting events on IndexedDB updates from another tab

如果我在多个选项卡中打开了 IndexedDB 数据库,我可以在不重新加载的情况下跟踪所有选项卡上的数据更改吗?

没有内置的方法可以单独使用 IndexedDB 来做到这一点。您基本上有两个选择:

  1. 以一定的频率轮询 IndexedDB 并检查新值

  2. 使用其他一些交叉表通信方式发送一个信号,表明您需要从 IndexedDB 检查新值。例如 localStorage(当发生变化时发出交叉表事件)或 BroadcastChannel(专为交叉表通信而设计,但没有完美的跨浏览器支持)。

为了扩展 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);
};

几点:

  • 频道无法向自己广播,所以它自己的同标签消息监听器函数将不会收到它的消息。但是,您可以在同一个选项卡上创建多个具有相同频道名称的频道实例,如果您需要该功能,每个频道都将收到其他频道的消息。
  • 频道应该是短暂的,所以完成后关闭频道。但是,这也可能是您希望频道在页面打开时保持打开状态的情况
  • 频道消息遵循与在数据库中存储对象类似的限制,例如您只能传递简单的 属性 值之类的数据,不能传递函数或自定义对象实例