前阵子做项目总结一下 indexedDB +web worker 开发中的问题,
mdn 上有 indexedDB 和 webworker 的文档,但是总觉得demo和实际使用有点出入,
项目中遇到的问题
- web worker 文档中提到的subworker chrome 并不支持,所以,不建议用,
- web worker 及indexedDB 文档demo有点简单,查询是最重要的资料最少
- indexedDB 查询出来的数据顺序和写入的顺序不一致(后面会提到)
需求背景
项目是内部项目只支持最新版本流览器
为什么要用indexedDB ,网上一大堆不再复述
开发中的需求
- 初始化数据 把数据写入indexedDB
- 更新数据,更新indexedDB
- 查询所有数据
- 查询指定单个key 所有数据
- 查询多个key 所有数据
代码结构划分
- 一个worker 负责把数据转换(如果需要的话)
- 一个worker 负责把数据写入indexedDB,
- 一个worker 负责监听检索消息,然后返回结果
- 一个模块负责提供对外操作indexedDB方法,数据检索
代码示例
示例下载 地址
git@github.com:yyccmmkk/testIndexedDB.git
写入indexedDB
示例代码包含完整的代码,这里不细贴出,只说一下写入遇到的问题,【写入顺序和检索结果顺序不致】
什么样的需求要求一致? 比如下拉框里的选择品牌 A开头完了B开头
【解决办法】
objectStore = db.createObjectStore("phones", {keyPath: "index", autoIncrement: true});
创建表时,指定keyPath 并且自增,这样就可以了。
写入前
{
"mKey":"1",
"mName":"A 华为",
"nKey":"11",
"nName":"HUAWEI Mate系列",
"oKey":"111",
"oName":"HUAWEI Mate RS 保时捷",
"pKey":"1111",
"pName":"64G",
"qKey":"11111",
"qName":"白色"
},
写入后
条件查询
- 首先创建索引,
- 根据索引进行检索
按条件查询,根据指定的条件查询,比如mKey ,mKey和oKey ,mKey nKey oKey
首先为了能够被检索 在写入时必须要创建对应的索引,如下图所示,
objectStore.createIndex("mKey", "mKey", {unique: false})
创建名为mKey 的索引,这个索引根据 指定的 mKey 值进行检索,
objectStore.createIndex("mnoKey", ['mKey', 'nKey', 'oKey'], {unique: false});
创建名为 mnoKey 的索引, 它根据指定的mKey nKey oKey 值 进行检索 demo代码已经给出,
关于query worker
这个worker 写了三个方法、getMKey、getMapKey、getOKey
getMKey: 使用游标检索指定objectStore内所有数据
getMapKey:使用索引,检索指定 索引值 数据,注意索引值是唯一的
getOKey:使用索引 游标 多条件检索数据
class Query {
//遍历所有品牌
getMKey(evt) {
let DBName = evt.data[1];
let storeName = evt.data[2];
let flag = evt.data[3];
let request = indexedDB.open(DBName);
request.onerror = (event)=> {
console.log('indexedDB error!')
};
request.onsuccess = (event)=> {
let db = request.result;
let transaction = db.transaction([storeName]);
let objectStore = transaction.objectStore(storeName);
let openCursor = objectStore.openCursor();
let temp = [];
openCursor.onsuccess = (evt)=> {
let cursor = evt.target.result;
if (cursor) {
temp.push(cursor.value);
cursor.continue();
}
};
transaction.oncomplete = (evt)=> {
postMessage([temp, flag])
};
};
}
//提取指定品牌
getMapKey(evt) {
let DBName = evt.data[1];
let storeName = evt.data[2];
let tempIndex = evt.data[3];
let id = evt.data[4];
let request = indexedDB.open(DBName);
request.onerror = (event) => {
console.log('indexedDB error!')
};
request.onsuccess = (event) => {
let db = request.result;
let transaction = db.transaction([storeName]);
let objectStore = transaction.objectStore(storeName);
let index = objectStore.index(tempIndex);
let tempData;
index.get(id).onsuccess = (event) => {
tempData = event.target.result;
};
transaction.oncomplete = (evt) => {
postMessage([tempData]);
};
};
}
getOKey(evt) {
let DBName = evt.data[1];
let storeName = evt.data[2];
let flag = evt.data[3];
let id = evt.data[4];
let tempIndex = evt.data[5];
let isSingle = evt.data[6];
let request = indexedDB.open(DBName);
request.onerror = (event) => {
console.log('indexedDB error!')
};
request.onsuccess = (event) => {
let db = request.result;
let transaction = db.transaction([storeName]);
let objectStore = transaction.objectStore(storeName);
let index = objectStore.index(tempIndex);
let singleKeyRange = IDBKeyRange.only(id);
let temp=[];
let cursor = index.openCursor(singleKeyRange, IDBCursor.NEXT);
cursor.onsuccess = (evt) => {
let cursor = evt.target.result;
if (cursor) {
temp.push(cursor.value);
!isSingle && cursor.continue();
}
};
cursor.onerror = (evt) => {
console.log(evt);
};
transaction.oncomplete = (evt) => {
postMessage(temp);
console.log(temp, flag)
};
};
}
}
let query = new Query();
onmessage = function (evt) {
query[evt.data[0]](evt)
};
....待续