【问题标题】:Is it possible to write objects to a file during an IndexedDb transaction?是否可以在 IndexedDb 事务期间将对象写入文件?
【发布时间】:2013-12-20 03:52:26
【问题描述】:

我有一个 objectStore,其中包含数百个对象,我可以使用如下代码查看:

db // already set by call to window.indexedDB.open
.transaction(["mailing-list"])
.objectStore("mailing-list")
.openCursor()
.onsuccess = function (event) {
    var cursor = event.target.result;
    if (cursor) {
        console.log(cursor.value);
        cursor.continue();
    }
};

我想要做的是使用 FileWriter 在检索到每个对象时写出它;我不想将所有对象累积在一个巨大的数组中并一次将它们全部写出来。我也不想为每个对象启动单独的事务,因为我想使用游标来遍历所有对象。 (不关心他们的钥匙。)

我会将对 fileWriter.write 的调用放在现在对 console.log 的调用处。对 cursor.continue() 的调用将在 onwrite 回调中。否则,我会在前一个完成之前发出写入,这是非法的。

这似乎是不可能的,因为写入是异步的,“onsuccess”回调将在 write 被调用后返回,从而结束事务并使光标无效,即使它是在闭包中捕获的。

我说得对吗?我将对其进行编码以在内存中累积整个对象集合,因此我可以在光标完成后编写它们,尽管这不是我的第一选择。

(注意:我不认为有同步的写作形式,但是,即使有,我也无法使用它,因为这段代码将在 Chrome 应用程序中。)

【问题讨论】:

  • 你可以将 cursor.value 发送给 writer,它不会随着事务消失。
  • 是的,第一个对象没问题。但是,当写入完成时,事务已经完成(当它的 onsuccess 函数返回时),所以光标不能前进到第二个对象。
  • 没有理由等待文件写出。只需向作者提供值并继续下一步()。您可以在事务期间打开一百万个文件句柄并将值传递给编写器。为什么要等着写呢?他们堆叠得很好。您可以在作者完成之前转到下一个。换句话说,您可能一次写入所有文件。这一切都是异步的,所以它只是工作。如果它不是非常简单,请重新考虑您的方法。
  • 我不认为这是正确的。根据 FileWriter.write (w3.org/TR/file-writer-api/#idl-def-FileWriter) 的规范:“如果 readyState 是 WRITING,则抛出 InvalidStateError 并终止这一系列步骤。” (我不确定您所说的“文件句柄”是什么意思。我可能应该强调我使用的是 W3C 文件 API,而不是通用文件 API。)
  • 我真的觉得你想多了。只需创建一个传递文件名和值的新保护程序函数,然后将 console.log 调用替换为对该函数的调用。 saver 函数应该创建一个新的 FileWriter 并将其设置为传递的值和文件名,完成需要多长时间或光标在写入时发生的情况无关紧要;该值已传递给保护程序函数。总之,如果console.log能做到,那么saver函数也能做到。

标签: javascript indexeddb filewriter


【解决方案1】:

只要两个异步处理器之间有足够的缓冲区,您就可以这样做。

我的博客有点关于这是如何做到的here:

考虑使用大分隔文本中的记录填充存储。为了避免为保存所有记录而占用内存,数据通过 CsvStreamer 使用 HTTP Range 标头按块下载,并在读取记录时调用下一个回调。一大块数据包含多条记录,在这种情况下,CsvStreamer 同步写入。在等待下一个数据块 CsvStreamer 异步调用下一个回调。

var db = new ydn.db.Storage(db_name, schema, options);
var stream = new CsvStreamer(url);
var isSerial = false;
var tdb = db.thread('multi', isSerial); // multi-request parallel transactions
var putData = function(data) {
  if (data) { 
    tdb.put('store1', data).then(function() {
      stream.next(function (data) {   
        putData(data);
    }), function(e) {
      throw e;
    });     
  }
});

stream.next(function (data) {
  putData(data);
}

诀窍是在事务仍然处于活动状态时重用它。否则创建一个新事务。

编辑:

是的,上面的例子是写到 idb,而你想读。在管道异步处理器时,您需要关注最慢的一个,即 FileWriter。这是一个例子:

var dump = function(marker) {
  var q = marker ? db.from('store name', '>', marker) : db.from('store name');
  q.open(function(cur) {
    var cb = writeToFile(cur.getValue());
    if (cb) { // wait me callback
       var next_key = cur.getKey();
       cb(function() {
         dump(next_key); // notice de-referencing cur, though not necessary
       });
       cb = null; // also not necessary, but better be on safe side of memory leak
       return null; // stop continuing cursor
    } else { // file writer said, good to call me again
      return undefined; // continue cursor
    }
  }, iter, 'readonly');
}

dump();

是否可以在 IndexedDb 事务期间将对象写入文件?

简短回答:不。

【讨论】:

  • 你的图书馆很有趣,我会研究一下。但是,从您引用的文章和您的示例中,我看不出它如何应用于迭代数据库并将检索到的对象写入文本文件。 (它是操作系统文件系统上的“外部”文件;我想到的操作是导出功能。)如果我不打算使用游标,那么将它分成多个事务是可行的。但我仍然看不到如何使用光标来遍历对象,这是我最初对我要解决的问题的陈述。
  • 在阅读您的 YDN-DB 库时,我对许可一无所知。它是什么类型的许可证?
  • 您是否在 Chrome 应用程序中测试过 YDN-DB,或者您知道它是否适用于 Chrome 应用程序强制执行的限制?
  • 是的,我在 chrome 应用程序和扩展程序中使用。许可证可以在每个源代码和缩小文件中找到。它是 Apache v2。
  • 谢谢!我会调查的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-19
  • 1970-01-01
  • 2016-12-02
  • 1970-01-01
  • 1970-01-01
  • 2014-09-12
  • 1970-01-01
相关资源
最近更新 更多