IndexedDB - Microsoft Edge .getAll 方法

IndexedDB - Microsoft Edge .getAll method

最近我一直在玩弄 IndexedDB - 主要使用 Google Chrome 作为我的调试工具。不幸的是,我很快就偶然发现了一个与浏览器之间的不兼容严格相关的问题——Edge 似乎不支持 IDBObjectStore 接口上的 .getAll method, 哎呀 .get 方法似乎也很棘手 - 到目前为止我的所有尝试都导致了以下错误消息:

Unable to get property 'message' of undefined or null reference

使用以下代码:

var db;
function estabilishConnection(callback) {
    var req = indexedDB.open('database', 1);
    req.onsuccess = function (evt) {
        db = evt.target.result;
        callback();
    }
    req.onupgradeneeded = function (evt) {
        var target = evt.currentTarget;
        var store = target.result.createObjectStore('object', {autoIncrement: true});
        store.add("sample1");
        store.add("sample2");
        store.add("sample3");
    }
}

function retrieveItems() {
    var transaction = db.transaction("object", "readonly");
    var handler = transaction.objectStore("object");

    var countRequest = handler.count();
    var total; 
    countRequest.onsuccess = function() {
        total = countRequest.result;
        for (var i = 0; i < total; i++) {
            var get = handler.get(i);
            console.log(get);
        }
    }
}

estabilishConnection(function(evt) {
    retrieveItems()
});

我的问题是:

a) 无需依赖 Dexie.js 等第三方库即可实现 .getAll 方法的最合适方法是什么?我假设即使遍历所有可用对象都有效,它仍然不是性能方面最明智的想法。

b) 如何让 get 方法在 Edge 中工作 -- 已经单独解决了它,不知何故下面的代码片段成功了,尽管获取所有值仍然是,至于现在,对我来说还是个谜:|

db.transaction('object').objectStore('object').get(1).onsuccess = function(event) {
    console.log(event.target.result);
};

好吧,我正式是个傻瓜,找到了解决方案here, I have absolutely no clue how I managed to miss it when searching for the solution earlier. Use IDBCursor接口。这是代码中的解决方案,以防有人遇到类似问题。

var retrievedItems = [];
    db.transaction('object').objectStore('object').openCursor().onsuccess = function(event) {
    var cursor = event.target.result;
    if(cursor) {
        retrievedItems.push(cursor.value);
        cursor.continue();
    } else {
        // no more keys remaining
        console.log(retrievedItems);
    }
};

错误消息表明处理程序变量为空。您确定要等到升级处理程序完成后才开始新事务吗?一种确定的方法是确保数据库打开请求已经解决。从它的外观来看,您的代码不会那样做。要等待,请执行以下操作:

var openRequest = indexedDB.open...;
openRequest.onsuccess = function() {
  var db = openRequest.result;
  var handle = db.transaction...;
  // ...
};

实际上,我不明白你为什么要这样称呼 handler.get。没有IDBTransaction.prototype.get方法。

此外,您可能想要研究 promises 以帮助您更清晰地构建流程。这是一个例子:

 function open(name, version, upgradeHandler) {
   return new Promise(function(resolve, reject) {
      var request = indexedDB.open(name,version);
      request.onupgradeneeded = upgradeHandler;
      request.onsuccess = () => resolve(request.result);
      request.onerror = () => reject(request.error);
   });
 }

 function myUgpradeHandler(event) {
   var db = event.target.result;
   var store = db.createObjectStore(...);
 }

 function getItems(db) {
   return new Promise(function(resolve, reject) {
      var tx = db.transaction(...);
      var request = tx.getAll();
      request.onsuccess = () => resolve(request.result);
      request.onerror = () => reject(request.error);
   });
 }

 async function foo() {
   var db = await open(name, version, myUpgradeHandler);
   var items = await getItems(db);
   for(var item of items) {
     console.log(item);
   }
 }