Chrome扩展:如何通过值从IndexedDB获取对象?
IndexedDB查询对象返回undefined的解决方法
问题场景
开发Chrome扩展时,需要实现逻辑:当对象的urlKeyValue不存在于IndexedDB时添加该对象;若已存在则获取对应对象。但在查询已存在对象时,objectStore.get(person.urlKeyValue)返回undefined。
对象结构示例
{ "message": "insert", "payload": [ { "urlKeyValue": "", "url": { "[userId]": { "[time]": { "msg": "form_data.get(\"message\")" } } } } ] }
核心函数代码
function insert_records(records, when) { if (db) { const insert_transaction = db.transaction(["roster2"], "readwrite"); const objectStore = insert_transaction.objectStore("roster2"); return new Promise((resolve, reject) => { insert_transaction.oncomplete = function () { console.log("ALL INSERT TRANSACTIONS COMPLETE."); resolve(true); }; insert_transaction.onerror = function () { console.log("PROBLEM INSERTING RECORDS."); resolve(false); }; records.forEach((person) => { if (when != "init") { const index = objectStore.index("urlKeyValue"); let search = index.get(person.urlKeyValue); search.onsuccess = function (event) { if (search.result === undefined) { let request = objectStore.add(person); request.onsuccess = function () { console.log("Added: ", person); }; } else { const request2 = objectStore.get(person.urlKeyValue); request2.onsuccess = function (event) { console.log("--------" + event.target.result); }; } }; } else { let request = objectStore.add(person); request.onsuccess = function () { console.log("Added: ", person); }; } }); }); } }
存储对象示例
let roster = [ { urlKeyValue: "https://www.youtube.com/", "https://www.youtube.com/": { 1: { 20: { msg: "this is some init data", }, }, }, }, ];
问题原因
objectStore.get()默认是根据对象仓库的主键查询,但urlKeyValue是你创建的索引字段而非主键,直接用它作为objectStore.get()的参数自然无法匹配到对象。另外,你在search.onsuccess回调里已经通过search.result拿到了查询结果,完全不需要重复发起查询请求。
解决方案
方案1:直接复用已查询到的结果
在else分支里直接使用search.result即可,无需再次查询:
search.onsuccess = function (event) { if (search.result === undefined) { let request = objectStore.add(person); request.onsuccess = function () { console.log("Added: ", person); }; } else { // 直接使用已获取的结果 console.log("--------", search.result); } };
方案2:通过索引重新查询(若需重复查询)
如果后续需要重新查询该对象,继续使用索引的get()方法,而非对象仓库的get():
else { const request2 = index.get(person.urlKeyValue); request2.onsuccess = function (event) { console.log("--------", event.target.result); }; }
方案3:将urlKeyValue设为主键(可选)
如果业务允许,创建对象仓库时将urlKeyValue设为主键,这样后续用objectStore.get(person.urlKeyValue)就能直接查询:
// 创建仓库时的示例代码 const objectStore = db.createObjectStore("roster2", { keyPath: "urlKeyValue" });
注意:需确保所有存储对象的urlKeyValue唯一且非空。
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

