IndexedDB:TransactionInactiveError

时间:2016-10-28 22:31:48

标签: javascript ajax indexeddb

在这一行:

 var request = store.add(obj); 

我收到错误:

  

TransactionInactiveError:针对事务发出了请求   目前尚未激活,或已完成。

我在使用AJAX时只收到错误。如何在事务完成之前确保AJAX完成?我试图将信息从sql数据库加载到objectstore中。当我用Google搜索错误时,我会获得有关交易和异步性质的信息,但我还没有找到具有代码的具体解决方案。

我已经调查了回调,承诺和超时(这对我来说感觉像是黑客攻击),但是我无法让这个异步调用工作。任何帮助将不胜感激。

var req = indexedDB.open(DB_NAME, DB_VERSION);
req.onsuccess = function () {
        db = this.result;
        var tx = db.transaction('tblFields', 'readwrite');
        var store = tx.objectStore('tblFields');

             $.ajax({
                    type: "POST",
                    url: "Off.aspx/GetFields",
                    data: '{}',
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    success: function (response) {
                        var customers = response.d;
                        $(customers).each(function () {
                            var obj = { measureID: this.measureID, measureName: this.measureName, fieldName: this.fieldName };
                            var request = store.add(obj);
                        });
                    },
                    failure: function (response) {
                        alert(response.d);
                    },
                    error: function (response) {
                        alert(response.d);
                    }
                });
}

2 个答案:

答案 0 :(得分:1)

您的成功回调是异步执行的。将事务初始化代码移动到回调中应该可以解决问题:

success: function (response) {
    var customers = response.d;
    var tx = db.transaction('tblFields', 'readwrite');
    var store = tx.objectStore('tblFields');
    $(customers).each(function () {
        var obj = { measureID: this.measureID, measureName: this.measureName, fieldName: this.fieldName };
        var request = store.add(obj);
    });
},

答案 1 :(得分:0)

如果indexedDB检测到某个事务没有活动请求,它会在短时间后关闭。当您发出ajax请求时,不会立即得到响应。在您发出ajax请求和获取响应之间,idb看不到使用该事务的活动idb请求,因此它会关闭事务。

解决方案很简单。首先执行ajax请求,然后执行idb事务。这是一些伪代码:

$.ajax({
  success: function(response) {
    var req = indexedDB.open(...);
    req.onsuccess = function(event) {
      var db = event.target.result; // or this.result, or req.result
      var tx = db.transaction(...);
      var store = tx.objectStore(...);
      for(var customer of response.d) {
        var obj = {...};
        store.add(obj);
      }
    };
  }
});

如果您想使用promises并可以访问ES6,请执行以下操作:

function dbconnect(name, version, upgrade) {
  return new Promise(function(resolve, reject) {
    var request = indexedDB.open(name, version);
    request.onupgradeneeded = upgrade;
    request.onsuccess = function(event) {
      var db = event.target.result;
      resolve(db);
    };
    request.onerror = function(event) {
      var error = event.target.error;
      reject(error);
    };
    request.onblocked = function(event) {
      console.warn('blocked, not fulfilling promise until unblocked');
    };
  });
}

function ajaxpostrequest(url) {
  return new Promise(function(resolve, reject) {
    $.ajax({
      type: 'post',
      data: '{}',
      contentType: 'application/json; charset=utf-8',
      dataType: 'json',
      url: url,
      success: resolve,
      failure: reject,
      error: reject
    });
  });
}

function addcustomer(db, customer) {
  return new Promise(function(resolve, reject) {
    var tx = db.transaction(...);
    var store = tx.objectStore(...);
    var obj = {measureId: customer.measureId, ...};
    var request = store.add(obj);
    request.onsuccess = function(event) {
      resolve();
    };
    request.onerror = function(event) {
      reject(event.target.error);
    };
  });
}


async function request_then_connect_then_put() {
  try {
    var response = await fetch(url, {method:'post'});
    console.log('fetched url');
    var json = await response.json();
    var customers = json.d;
    console.log('read json object from text of url');
    var db = await dbconnect(...);
    console.log('connected to database', db.name);
    var addpromises = customers.map((customer) => addcustomer(db, customer));
    var result = await Promise.all(addpromises); 
    console.log('stored all customer object things');
  } catch(error) {
    console.debug(error);
  }
}