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

Old*_*zer 4 javascript indexeddb

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

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 });
    };
Run Code Online (Sandbox Code Playgroud)

这适用于版本3和版本4.当它来到版本5时,我收到错误:

无法在"IDBDatabase"上执行"createObjectStore":具有指定名称的对象库已存在.在IDBOpenDBRequest.DBOpenRequest.onupgradeneeded

是不是createObjectStore操作新版本的数据库是空的?我该如何修复错误?

我碰巧记录了db对象,详细信息如下:

在此输入图像描述

我很好奇为什么版本号在摘要行和扩展时有所不同.

Jos*_*ell 11

是不是在新版本的数据库上运行的createObjectStore是空的?

当你得到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
    // ...
  }
}
Run Code Online (Sandbox Code Playgroud)

我很好奇为什么版本号在摘要行和扩展时有所不同.

那个是微妙的...我相信在5记录数据库已开始升级的那一刻.但是因为在upgradeneeded处理程序中抛出了异常,所以升级被中止,版本号在4记录详细信息之前回滚到了.


Fel*_*uis 7

升级数据库的最佳方法是检查商店名称是否已存在。在此示例中,我使用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 })
    }
  }
})
Run Code Online (Sandbox Code Playgroud)

如果您需要检查一个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 });
    }
  }
})
Run Code Online (Sandbox Code Playgroud)

使用带有 indexNames 和 objectStoreNames 的 indexDB API 来检查某些内容是否存在,使我的代码更加可靠且易于维护,在使用数据库版本控制使用 IndexDB中也简要提到了这一点