10

我在 IndexedDB 中存储了大量的小对象。我想让用户能够将其中一个对象存储导出到他们可以“下载”的文件中。

我已经阅读了这篇博客文章。其中描述了读取数据、读取JSON.stringify数据、使用 对其进行编码encodeURIComponent以及将其放置为href可用于下载数据的链接。像这样的东西:

var transaction = db.transaction([objectstore], "readonly");
var content = [];
var objectStore = transaction.objectStore(objectstore);

objectStore.openCursor().onsuccess = function(event) {
    var cursor = event.target.result;
    if (cursor) {
        content.push({key:cursor.key,value:cursor.value});
        cursor.continue();
    }
}; 

transaction.oncomplete = function(event) {
    var serializedData = JSON.stringify(dataToStore);
    link.attr("href",'data:Application/octet-stream,'+encodeURIComponent(serializedData));
    link.trigger("click");
};

这很好,除了对象存储将有数百万条记录,而且我觉得这还不够高效。有没有办法更直接地允许用户将对象存储另存为文件(以我可以通过网页再次导入的方式)。


编辑从评论中的一些注释中,我重写了一些它是如何工作的,以便从中获得更多的汁液。新代码类似于:

var transaction = db.transaction([objectstore], "readonly");
var objectStore = transaction.objectStore(objectstore);

objectStore.getAll().onsuccess = function(evt) {
    var url = window.URL.createObjectURL(new Blob(evt.target.results, {'type': 'application/octet-stream'}));
    link.attr('href', url);
    link.trigger('click');
};

这会给我这样的结果:

  • 10k 条记录,975.87ms 平均导出时间
  • 100k 条记录,5,850.10ms 平均导出时间
  • 100 万条记录,平均导出时间为 56,681.00 毫秒

如您所见,导出 100 万条记录大约需要一分钟。有没有更好的方法来做到这一点?(我也尝试使用游标代替.getAll(),但游标速度较慢)

4

1 回答 1

1

IDBObjectStore.getAll不是 IndexedDB 标准的一部分,它在幕后使用游标。

注意:Mozilla 还实现了 getAll() 来处理这种情况(以及 getAllKeys(),它目前隐藏在 about:config 中的 dom.indexedDB.experimental 首选项后面)。这些不是 IndexedDB 标准的一部分,因此将来可能会消失。我们将它们包括在内是因为我们认为它们很有用。下面的代码和上面做的完全一样:

objectStore.getAll().onsuccess = function(event) {
  alert("Got all customers: " + event.target.result);
};

查看游标的 value 属性会带来性能成本,因为对象是惰性创建的。例如,当您使用 getAll() 时,Gecko 必须一次创建所有对象。例如,如果您只对查看每个键感兴趣,则使用游标比使用 getAll() 更有效。但是,如果您尝试获取对象存储中所有对象的数组,请使用 getAll()。

获取不知道密钥的记录的唯一方法是使用游标。所以不,我认为没有更好的方法。但是您需要问自己这是否比从服务器获取记录更快。

于 2014-02-20T23:01:30.067 回答