Luk*_*uke 5 html javascript javascript-events google-chrome-extension indexeddb
我正在编写一个 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)");
}
}
Run Code Online (Sandbox Code Playgroud)
……但我确实在乎。
所以,我目前正在做的是在upgrade(event)
函数内部放置一个条件来检查event.oldVersion
(在全新安装时为 0)的真实性。如果该值大于 0,那么我会打开一个新选项卡,其中包含一个选项页面,用户可以在其中挑选和选择他想要更新的对象。
现在是棘手的部分:一旦此页面关闭,我需要向包含必要升级信息的后台页面发送一条消息。通常,我只会在我的侦听器中接收消息并使用提供的信息执行更新。但是,IDBDatabase.createObjectStore()
抛出一个InvalidStateError
if:
该方法 [is] 不是从 versionchange 事务回调中调用的。
当我查看 的规范时IDBDatabase.transaction(storenames, mode)
,在mode
参数描述中,它说:
versionchange
此处无法指定模式。
因此,在我看来,我需要触发一个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});
}
}
Run Code Online (Sandbox Code Playgroud)