获取对象存储已经存在于 onupgradeneeded 中

Getting object store already exists inside onupgradeneeded

我的代码如下(通常是知名对象的命名约定):

var DBOpenRequest = window.indexedDB.open("messages", 6);
//...
DBOpenRequest.onupgradeneeded = function(event) { 
  console.log("Need to upgrade.");
  var db = event.target.result;
  console.log(db);

  db.onerror = function(event) {
     console.log("Error upgrading.");
  };

  // Create an objectStore for this database
  var objectStore = db.createObjectStore("messages", { keyPath: "id", autoIncrement: true });
    };

这个 运行 适用于版本 3 和 4。当涉及到版本 5 时,我得到错误:

Failed to execute 'createObjectStore' on 'IDBDatabase': An object store with the specified name already exists. at IDBOpenDBRequest.DBOpenRequest.onupgradeneeded

createObjectStore 不是在新版本的空数据库上运行吗?我该如何修复错误?

我碰巧记录了 db 对象,详情如下:

我很好奇为什么摘要行中的版本号和展开后的版本号不同。

Isn't the createObjectStore operating on a new version of the database which is empty?

当您得到 upgradeneeded 时,数据库处于您之前保留的任何状态。由于您不知道用户将访问您的代码的哪个版本,因此您需要查看事件的 oldVersion 以找出那是什么。典型的模式是这样的:

var rq = indexedDB.open('db', 5);
rq.onupgradeneeded = function(e) {
  var db = rq.result;
  if (e.oldVersion < 1) {
    // do initial schema creation
    db.createObjectStore('users');
  }
  if (e.oldVersion < 2) {
    // do 1->2 upgrade
    var s = db.createObjectStore('better_users');
    s.createIndex('some_index', ...);
    db.deleteObjectStore('users'); // migrating data would be better
  }
  if (e.oldVersion < 3) {
    // do 2->3 upgrade
    rq.transaction.objectStore('better_users').createIndex('index2', ...);
  }
  if (e.oldVersion < 4) {
    // do 3->4 upgrade
    db.createObjectStore('messages', ...);
  }
  if (e.oldVersion < 5) {
    // do 4->5 upgrade
    // ...
  }
}

I am curious why the version number is different in the summary line and when expanded.

那个很微妙...我相信在记录 5 时数据库已经开始升级。但是 because an exception was thrown in the upgradeneeded handler the upgrade was aborted, and the version number was rolled back4 之前详细信息被记录。

升级数据库的最佳方法是检查商店名称是否已经存在。在这个例子中,我使用 https://npmjs.com/idb

openDB('db-name', version, {
  upgrade(db, oldVersion, newVersion, transaction) {
    if(!db.objectStoreNames.contains('messages')) {
      db.createObjectStore('messages', { keyPath: "id", autoIncrement: true })
    }
  }
})

如果您需要检查 indexName 是否已经存在,您可以获取 objectStore 并检查 indexNames 属性 是否包含您需要的 indexName。

openDB('db-name', version, {
  upgrade(db, oldVersion, newVersion, transaction) {
    const storeName = transaction.objectStore('storeName')
    if(!storeName.indexNames.contains('indexName')) {
        storeName.createIndex('indexName', 'propertyName', { unique: false });
    }
  }
})

将 indexDB API 与 indexNames 和 objectStoreNames 一起使用来检查是否存在某些内容使我的代码方式更加可靠且易于维护,Working with IndexDB Using database versioning[=14 中也简要提到了这一点=]