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
2 Answers
Reset to default 6If 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);
});
},