我正在编写一个chrome扩展,该扩展使用 IndexedDB
在 IDBObjectStore
内的 IDBDatabase
中存储一些信息客户端。
数据的性质使得我需要我的用户能够一时兴起地修改对象存储。 (添加新对象修改现有对象等。)我正在通过设置页面完成此操作,到目前为止一切正常。
当我要发布(默认)对象存储库的新版本时,需要提出警告。如果我不在乎覆盖用户数据,那么我可以像处理全新安装那样触发 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)");
}
}
...但是我很在乎。
因此,我目前正在做的是在
upgrade(event)
函数内部放置一个条件,该条件检查 event.oldVersion
的真实性(在全新安装中为0)。如果该值大于0,则我将打开一个新选项卡,其中包含一个选项页,用户可以在其中选择并选择要更新的对象。现在棘手的部分:该页面关闭后,我需要向后台页面发送一条消息,其中包含必要的升级信息。通常,我只会在侦听器中接收到消息并利用提供的信息执行更新。但是,如果出现以下情况,
IDBDatabase.createObjectStore()
会抛出InvalidStateError
:当我在
IDBDatabase.transaction(storenames, mode)
参数描述中查看 mode
的规范时,它说:因此,在我看来,我似乎需要触发
onupgradeneeded
事件,但除了事件本身之外,还需要向事件处理程序传递一个附加参数,该参数包含可用于决定如何执行升级的信息。我不知道该怎么做。
谁能给我一些见识?
最佳答案
您正在获取InvalidStateError
,因为您可能没有从IDBDatabase.createObjectStore()
事件处理程序中调用onupgradeneeded
。对于IDB,所有对象库的创建和操作都必须在onupgradeneeded
事件处理程序内部进行,或者在onupgradeneeded
触发之后进行。
如果我正确理解了您的要求,那么您就不想在某些情况下覆盖用户现有的对象存储,为此,您希望在onupgradeneeded
事件处理程序中传递一些信息以告知是创建新的对象存储还是在顶部进行一些修改。现有的对象库。
我的建议是-具有2个全局数组变量DB_SCHEMA_DROP_QUERIES
和DB_SCHEMA_CREATE_QUERIES
,您可以使用drop准备它们并创建数据,然后再使用window.indexedDB.open(DB_NAME, CURRENT_DB_VERSION);
打开数据库
然后输入下面的代码(我只是提一个提示),所以当您想要 1. 创建一个新的数据库,然后首先从数据库中删除所有现有的数据存储并创建新的(意味着同时填充DB_SCHEMA_DROP_QUERIES
和DB_SCHEMA_CREATE_QUERIES
)。 2. 只需再添加一个对象存储,然后仅准备DB_SCHEMA_CREATE_QUERIES
3. 修改现有的对象存储,然后同时准备DB_SCHEMA_DROP_QUERIES
和DB_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});
}
}