为什么对 IDBObjectStore.get() 的调用会导致混淆行为?

Why is this call to IDBObjectStore.get() is resulting in confusing behavior?

我正在尝试掌握使用 indexedDB 在客户端存储数据的窍门。

考虑以下代码:

function queryURL(message, sender)
{
    chrome.contextMenus.removeAll();

    var openRequest = indexedDB.open("Tags",1);
    openRequest.onsuccess = function(event){
        var queryURL = message['host'];
        var db = event.target.result;
        var objectStore = db.transaction("domains").objectStore("domains");
        var query = objectStore.get(queryURL);

        query.onsuccess = function(event){                                                                                                                                                                                                                     
            alert(query.result);
            delete query.result["domain"];
            createMenuItems(query.result);
            available_commands=request.result;        
        };

        db.onerror = function(event){
            console.log("an error bubbled up during a transaction.");
        };

    };
    openRequest.onerror = function(event){
        console.log("error opening DB");
    };  
}  

我不完全理解查询中应该发生什么。

无论查询的key是否在数据库中,结果都是一样的: query.onsuccess() 运行并且 query.resultundefined 所以 代码错误并在我尝试从中删除密钥时立即退出 query.result

如果没有找到,query.onsuccess()应该没有 运行,对吗?

如果 找到了 query.result 应该持有那个对象 对应那个键,对吗?


如果有帮助,这里是我用来初始化数据库的代码:

const db_name="Tags";                                                                                                                                                                                                                                          


var request = window.indexedDB.open(db_name, 1); 
var tags  = [ 
    //codes: 0 - markdown wrap tag
    //       1 - HTML wrap tag 
    //       2 - single tag
    { domain: "www.youtube.com", 

      bold:["*",0],
      strikethrough:["-",0],
      italic:["_",0] 
    },  


    { domain: "www.whosebug.com", 

      bold:["<strong>",1], 
      italic:["<em>",1],
      strikethrough:["<del>",1],
      superscript:["<sup>",1],
      subscript:["<sub>",1],
      heading1:["<h1>",1],
      heading2:["<h2>",1],
      heading3:["<h3>",1],
      blockquote:["<blockquote>",1],
      code:["<code>",1],
      newline:["<br>",2],
      horizontal:["<hr>",2]
    }   
];


request.onerror = function(event) {
  alert("Error opening the database");
};

request.onupgradeneeded = function(event) {
    var db = event.target.result;
    alert("I'm doing stuff!"); 
    var objectStore = db.createObjectStore("domains", {keyPath: "domain" }); 
    objectStore.createIndex("domain", "domain", { unique: true }); 

    objectStore.transaction.onComplete = function(event) {
        var domanStore=db.transaction("domains","readwrite").objectStore("domains");
        for(var i in tags)
        {
            domainStore.add(tags[i]);
        }
    }   
};

以下是我正在使用的资源的一些链接:

Using IndexedDB

IDBObjectStore

IDBRequest

发现结果为空或undefined即查询成功。所以是的,你得到 onsuccess 电话 result === undefined.

onerror 仅在某些 中断 时保留,例如您提供了无效的密钥。

来自IDBObjectStore.get docs

Note: This method produces the same result for: a) a record that doesn't exist in the database and b) a record that has an undefined value. To tell these situations apart, call the openCursor() method with the same key. That method provides a cursor if the record exists, and no cursor if it does not.

是的。当 delete 方法 return 成功时更令人困惑,即使没有记录被删除。

由于请求错误事件是可取消的冒泡事件,即使没有找到记录也无法调用错误回调。如果请求出错并且错误没有被阻止,它的事务将被中止并且 indexedDB.onerror 也会被调用。所以用未定义的结果调用成功仍然比调用错误更好。