最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - IndexedDB: TransactionInactiveError - Stack Overflow

programmeradmin2浏览0评论

At this line:

 var request = store.add(obj); 

I get the error:

TransactionInactiveError: A request was placed against a transaction which is currently not active, or which is finished.

I only get the error when I use AJAX. How do I make sure the AJAX pletes before transaction finishes? I'm trying to load info from a sql database into the objectstore. When I've googled the error, I get info about transactions and the asynchronous nature, but I haven't found a concrete solution with code.

I've looked into callbacks, promises, and timeouts (which feels like a hack to me), but I can't get this asynchronous call to work. Any help would be greatly appreciated.

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);
                    }
                });
}

At this line:

 var request = store.add(obj); 

I get the error:

TransactionInactiveError: A request was placed against a transaction which is currently not active, or which is finished.

I only get the error when I use AJAX. How do I make sure the AJAX pletes before transaction finishes? I'm trying to load info from a sql database into the objectstore. When I've googled the error, I get info about transactions and the asynchronous nature, but I haven't found a concrete solution with code.

I've looked into callbacks, promises, and timeouts (which feels like a hack to me), but I can't get this asynchronous call to work. Any help would be greatly appreciated.

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);
                    }
                });
}
Share Improve this question edited Oct 29, 2016 at 0:36 sideshowbarker 88.6k30 gold badges215 silver badges212 bronze badges asked Oct 28, 2016 at 22:31 lselse 231 silver badge3 bronze badges 0
Add a ment  | 

2 Answers 2

Reset to default 6

If indexedDB detects no active requests on a transaction it closes after a short period of time. When you make an ajax request, that does not get a response immediately. In between the time you make the ajax request and get a response, idb sees no active idb requests using the transaction so it closes the transaction.

The solution is simple. Do the ajax request first, then do the idb transaction. Here is some pseudocode:

$.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);
      }
    };
  }
});

If you want to use promises and have access to ES6, do something like this:

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);
  }
}

Your success callback is executing asynchronously. Moving the transaction initialization code into the callback should resolve the issue:

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);
    });
},
发布评论

评论列表(0)

  1. 暂无评论