在回调中重用IDBTransaction会抛出TransactionInactiveError

时间:2016-06-22 12:41:30

标签: javascript indexeddb

我正在开发一个广泛使用 IndexedDB 的应用。我要做的是保存员工表和公司表的数据。

每个员工属于公司和员工对象我've Company's ID,两个实体的对象都是这样的。

公司的目标:

{"id":1,"name":"ABC"}

员工的对象:

{"id":100,"name":"E1","company_id":1}

我使用自动递增的密钥(称为appid)来保存公司的详细信息,因此我公司的最终对象如下所示:

{"id":1,"name":"ABC","appid":1}

当我逐个插入公司记录时,appid将自动递增。
现在在插入员工的对象时,我想找到公司的localid(appid)并将其保存在员工的对象中,以使员工的对象看起来像:

{"id":100,"name":"E1","company_id":1,"company_app_id":1}

我可以通过调用方法获取公司的localid,同时保存员工的详细信息,例如:

var transaction = db.transaction(['employees'], 'readwrite');
var objStore = transaction.objectStore('employees');
var company_id=employeeobject.company_id;
companyDB.getCompanyById(company_id,function(companyObject){
      transaction = db.transaction(['employees'], 'readwrite');
      objStore = transaction.objectStore('employees');
      // If I comment above two lines it throws me exception.
      var request=objStore.put(employeeobject);
      request.onsuccess = function (e) {
          // using it for next insertion.
      };
});

上述代码的问题是每次我想在表中插入员工的数据时我需要重新打开回调函数中的trascation,因为如果我不再次打开事务,它会抛出 TransactionInactiveError

我在SO上搜索了特定的错误,发现只要在当前范围内不再使用事务,事务就会变为非活动状态。

  

当我有几个员工的对象时,上面的代码工作得很好。   但是当我尝试使用~1K的数据执行相同的代码时   (正常执行时间x~10)。

按正常执行时间,我的意思是没有获取公司的localid并直接保存员工的详细信息。

所以我的问题是,我能用最短的执行时间插入员工数据的最佳方式是什么,包括公司的localid?或者我做错了什么?

2 个答案:

答案 0 :(得分:1)

这取决于您如何实施companyDB.getCompanyById()

如上所述,它是一个异步黑匣子(也许它正在做网络请求?)正如您所发现的那样,索引数据库事务仅在创建后直接激活(1) (2)在来自该事务中发出的请求的回调中,直到"控制返回到事件循环"。如果没有进一步的细节,最好的办法就是批量处理工作 - 对N名员工进行getCompanyById()查询,然后编写N条记录。

但是从顶部的描述" ...员工表和公司表的数据......"也许这都在一个索引数据库数据库中,在这种情况下只需使用一个事务:

 var tx = db.transaction(['companies', 'employees'], 'readwrite');
 employee_records.forEach(function(record) {
   var company_id = record.company_id;
   var req = tx.objectStore('companies').get(company_id);
   req.onsuccess = function() {
     var company = req.result;
     record.company_app_id = company.app_id;
     tx.objectStore('employees').put(record);
   };
 });

(我在这里修改你的实际数据/逻辑,这只是为了说明)

答案 1 :(得分:0)

嗯,也许这样的事情有帮助吗?

function addCompany(db, company, callback) {
  var tx = db.transaction('companies', 'readwrite');
  var store = tx.objectStore('companies');
  var request = store.add(company);
  request.onsuccess = callback;
}

function addEmployee(db, employee, callback) {
  var tx = db.transaction('employees', 'readwrite');
  var store = tx.objectStore('employees');
  var request = store.add(employee);
  request.onsuccess = callback;
}


function addCompanyThenEmployee(db, company, employee, callback) {
  addCompany(db, company, onAddCompany);

  function onAddCompany(event) {
    var newAppId = event.target.result;
    employee.company_app_id = newAppId;
    addEmployee(db, employee, callback);
  }
}


var company = {'id': 1, 'name': 'xyz'};
var employee = {'id': 1, 'name': 'xyz'};

var request = indexedDB.open(...);
request.onsuccess = function(event) {
  var db = event.target.result;
  addCompanyThenEmployee(db, company, employee, onAddCompanyThenEmployee.bind(null, company, employee));
};

function onAddCompanyThenEmployee(company, employee, event) {
  console.log('Added company', company, 'and employee', employee);
};