填充许多ObjectStore时的IndexedDB,错误:无法在'IDBDatabase'上执行'transaction':版本更改事务正在运行

时间:2017-02-22 01:14:59

标签: javascript indexeddb fetch-api

好的@Josh在填充IndexedDB ObjectStores时已经回答了有关错误消息的类似问题:

Failed to execute 'transaction' on 'IDBDatabase': A version change transaction is running

答案适用于仅填充一个ObjectStore的情况。但是在我的情况下,我需要填充至少5个ObjectStores。

我可以通过循环遍历列表来创建和填充所有ObjectStore,该列表包含创建和填充每个所需的所有数据。脚本工作正常,大部分时间,但是我发现了一个缺陷,所以每次执行都没有完美无缺,执行一些后,我收到了上述消息。

如答案中所述,该问题与执行时间有关。基于发布的解决方案,我修改了我的代码,以便在创建和填充的所有过程中使用相同的事务。但是在执行时,会出现一个新错误:

Uncaught TransactionInactiveError: Failed to execute 'put' on 'IDBObjectStore': The transaction has finished.

@Josh再次解决了这个问题。

如何在没有任何先前错误的情况下完美填充最近创建的ObjectStore?这是代码:

 var db;
 function createPopulate(DB_NAME, DB_VERSION) {
   const datastores = [
   {osName:'a', osEndpoint:'/a', osKeyPath:'id',....},
   {osName:'b', osEndpoint:'/b', osKeyPath:'id',....},
   {osName:'c', osEndpoint:'/c', osKeyPath:'id',....}
   ];

   var request = indexedDB.open(DB_NAME, DB_VERSION);
   request.onupgradeneeded = function(e) {
     db = this.result;
     var tx = e.target.transaction;

     for (i in datastores) {
      // ObjectoStore created
      // Index created
      var customObjectStore = tx.objectStore(datastores[i].osName, "readwrite");
      popTable(customObjectStore, datastores[i].osEndpoint);
     }
  };

在函数内部,有popTable函数,它使用fetch函数fetch API获取数据并填充给定的ObjectStore:

function poptable(parameter, endPoint) 
     fetchGet2(endPoint, populate, parameter);
        function populate(json, parameter) {
           for (var m in json) {
              parameter.add(json[m]);
           }
        }
}

运行代码时,我收到此消息:

  DOMException: Failed to execute 'add' on 'IDBObjectStore': The transaction has finished.

如果修改脚本以仅执行popTable oncomplete事件,则错误消息为:

  DOMException: Failed to execute 'objectStore' on 'IDBTransaction': The transaction has finished.   at IDBTransaction.objectStore.transaction.oncomplete.

如何避免这些错误?

1 个答案:

答案 0 :(得分:2)

在等待其他异步事件发生时,您无法保持事务处于打开状态,这就是您在fetchGet2中所做的事情。每当所有请求都完成时,事务会自动提交,这基本上意味着如果您在其中一个请求的事件处理程序中打开事务 make后,您有一个请求不同步生成(可以任意嵌套),然后你的事务将在执行该请求之前提交。

在向IndexedDB写入任何内容之前,您必须先进行所有数据提取,否则您将不得不为每次提取使用单独的事务。