在多个选项卡中使用 indexeddb 操作

Sub*_*esh 11 javascript indexeddb

我试图将数据从一个选项卡保存到 indexeddb 并尝试从另一个选项卡获取数据。但是操作发生在第二个选项卡中,只有当我关闭第一个选项卡或使用 indexeddb.close() 关闭第一个选项卡中的 indexeddb 时;

如何从其他选项卡中的 indexeddb 获取数据(不关闭第一个选项卡或第一个选项卡中的 indexeddb 实例)?

Jos*_*osh 7

存储在 indexedDB 中的数据可用于来自同一来源的所有选项卡。首先澄清两个选项卡都指向同一个原点。

但是,indexedDB 基本上一次将对其数据的访问锁定在一个选项卡上。如果您在一个选项卡中打开了到 indexedDB 数据库的连接,并尝试在第二个选项卡中打开到同一数据库的连接,则第二个连接会停止,因为它被另一个选项卡中打开的连接阻止

请注意,我说的是停顿,而不是失败。这是因为一旦具有打开连接的选项卡关闭连接,连接最终将成功(它变得不受阻止)。一旦解除阻塞,尝试打开连接的成功事件最终将触发。

可以通过在打开的连接上调用 IDBDatabase.prototype.close 或简单地关闭选项卡来关闭连接。

避免一些不需要的行为并最小化阻塞事件发生频率的一种方法是避免使用全局数据库连接。全局我的意思是一个数据库连接,您在打开选项卡的时间附近,加载 dom 等时打开该连接,然后在选项卡的剩余生命周期内保持打开状态。不要在选项卡的整个生命周期内打开一次连接,而是仅在需要时打开连接,然后关闭它,并在每次需要时重新打开一个连接,此后关闭它。这样,连接在选项卡打开的大部分时间关闭,而不是在大部分时间打开。

有了所有这些借口,你的问题的答案是:

  1. 在第一个选项卡中,打开一个连接,写入数据,然后关闭连接。
  2. 不关闭第一个选项卡,然后在第二个选项卡中,打开一个连接,读取数据,然后关闭连接。

注意'blocked'事件。在 tab2 中添加一个监听器来监听它。如果您目睹了此事件,那么您尝试在 tab2 中进行连接,而 tab1 连接仍处于打开状态。更改您的应用程序以能够对这种情况做出反应。

这是侦听阻塞事件的简单示例:

function open(name, version, callback) {
  var request = indexedDB.open(name, version);
  request.onsuccess = function(event) {
    var db = request.result;
    callback(result, null);
  };
  request.onerror = function(event) {
    console.log('Failed to connect');
    callback(null, 'error');
  };
  request.onblocked = function(event) {
    console.log('Failed to connect because blocked');
    callback(null, 'blocked');
  };
}


open('foo', 1, function onopen(db, error) {
  if(error === 'error') {
    console.log('cannot do stuff because of error');
  } else if(error === 'blocked') {
    console.log('cannot do stuff because blocked');
  } else {
    console.log('do stuff with db', db.name);

    // do db operation here

    // cleanup when done
    db.close();
  }
});
Run Code Online (Sandbox Code Playgroud)

  • 锁定到单个选项卡仅适用于执行版本更改(例如升级或删除数据库)。这应该仅在您的 Web 应用程序需要修改数据架构时发生。如果您在正常使用数据库期间执行数据库版本更改,那么您正在以一种非常不寻常的方式使用 API。 (11认同)