IndexedDB:你能手动发起版本更改事务吗?

Luk*_*uke 5 html javascript javascript-events google-chrome-extension indexeddb

我正在编写一个 chrome 扩展,IndexedDB用于IDBObjectStoreIDBDatabase.

数据的性质是这样的,我需要我的用户能够随心所欲地修改对象存储。(添加新对象修改现有对象等)我正在通过设置页面完成此操作,到目前为止一切都很好。

当我想发布(默认)对象存储的新版本时,需要注意。如果我不关心覆盖我用户的数据,那么我可以像处理onupgradeneeded事件一样处理事件,当它被触发以响应全新安装时。这将是这样的:

var request = window.indexedDB.open(DB_NAME, CURRENT_DB_VERSION);
request.onupgradeneeded = upgrade;
function upgrade(event){
  var db = event.target.result;
  var objectStore = db.createObjectStore("domains", {keyPath: "id", autoIncrement: true});
  objectStore.createIndex("domain", "domain", {multiEntry: true });
  for(var i=0; i<tags.length; i++){
    objectStore.add(tags[i]);
    console.log("added " + tags[i]["domain"] + " to the IDBObjectStore 'domains' in the IDBDatabase 'Tags' (Format)");
  }
}
Run Code Online (Sandbox Code Playgroud)

……但我确实在乎。

所以,我目前正在做的是在upgrade(event)函数内部放置一个条件来检查event.oldVersion(在全新安装时为 0)的真实性。如果该值大于 0,那么我会打开一个新选项卡,其中包含一个选项页面,用户可以在其中挑选和选择他想要更新的对象。

现在是棘手的部分:一旦此页面关闭,我需要向包含必要升级信息的后台页面发送一条消息。通常,我只会在我的侦听器中接收消息并使用提供的信息执行更新。但是,IDBDatabase.createObjectStore()抛出一个InvalidStateErrorif:

该方法 [is] 不是从 versionchange 事务回调中调用的。

当我查看 的规范时IDBDatabase.transaction(storenames, mode),在mode参数描述中,它说:

versionchange 此处无法指定模式。

因此,在我看来,我需要触发一个onupgradeneeded事件,但除了事件本身之外,我还需要向事件处理程序传递一个附加参数,该参数包含可用于决定如何执行升级的信息。

我不知道如何去做这件事。

谁能给我一些见解?

hag*_*wal 4

您之所以会收到这样的消息,是InvalidStateError因为您可能不是IDBDatabase.createObjectStore()onupgradeneeded事件处理程序调用的。对于 IDB,所有对象存储创建和操作都必须在onupgradeneeded事件处理程序内部或onupgradeneeded触发后进行。

如果我正确理解您的要求,那么您不想在某些条件下覆盖用户现有的对象存储,为此您希望传递一些信息onupgradeneeded事件处理程序中传递一些信息来告知是否重新创建对象存储或在现有对象存储的基础上进行一些修改对象存储。

我的建议是 - 有 2 个全局数组变量DB_SCHEMA_DROP_QUERIESDB_SCHEMA_CREATE_QUERIES您可以在打开数据库之前使用 drop 和创建数据来准备它们window.indexedDB.open(DB_NAME, CURRENT_DB_VERSION);

然后有如下代码(我只是提醒一下),所以当您想要1. 创建新数据库时,首先从数据库中删除所有现有的数据存储并创建新的(这意味着填充 和DB_SCHEMA_DROP_QUERIESDB_SCHEMA_CREATE_QUERIES2.只需再添加一个对象存储,然后仅准备DB_SCHEMA_CREATE_QUERIES 3.修改现有对象存储,然后准备两者DB_SCHEMA_DROP_QUERIESDB_SCHEMA_CREATE_QUERIES但仅针对该特定对象存储

基本上我们想要实现的目标是使事物变得动态,而不是像这样硬编码数据存储创建db.createObjectStore("domains", {keyPath: "id", autoIncrement: true});。这也将帮助您摆脱维护版本记录的麻烦。

var dropQueriesLength = DB_SCHEMA_DROP_QUERIES.length;
for(var i =0; i < dropQueriesLength; i++){
try{
    DB_HANDLER.deleteObjectStore(DB_SCHEMA_DROP_QUERIES[i].name);
} catch(e){

}
}

for(var i =0; i < DB_SCHEMA_CREATE_QUERIES.length; i++){
  var objectStore = null;
    if(DB_SCHEMA_CREATE_QUERIES[i].primaryKeyCol != null && DB_SCHEMA_CREATE_QUERIES[i].primaryKeyCol != undefined){
        objectStore = DB_HANDLER.createObjectStore(DB_SCHEMA_CREATE_QUERIES[i].name, { keyPath: DB_SCHEMA_CREATE_QUERIES[i].primaryKeyCol});
    }
}
Run Code Online (Sandbox Code Playgroud)