我想在indexeddb的异步模式下做一些事情而且我失败了。你对我的问题有所了解吗?
代码:
function test(basekey) {
window.indexedDB.deleteDatabase("base");
var lConnection = window.indexedDB.open("base", 1);
lConnection.onsuccess = function (event) {
var lDB = event.target.result;
var lTransactionGlobal = lDB.transaction(['person'], 'readwrite');
var lTransactionTable = lTransactionGlobal.objectStore('person');
var lRequest = lTransactionTable.add({key: basekey+1, name:"me"});
lRequest.onsuccess = function (e) {
window.setTimeout(function () {
console.log("Second wrote");
lRequest = lTransactionTable.add({key: basekey+2, name:"you"});
lRequest.onsuccess = function () {
lDB.close();
};
lRequest.onerror = function () {
console.error("Request 2 failed");
};
}, 0);
};
lRequest.onerror = function () {
console.error("Request 1 failed");
};
};
lConnection.onblocked = function () { console.log("Blocked"); };
lConnection.onerror = function () { console.log("Error"); };
lConnection.onupgradeneeded = function (pEvent) {
var db = pEvent.target.result;
var objectStore = db.createObjectStore("person", { keyPath: "key" });
};
}
当我调用test(0)时,第二次“添加”时出现此错误:
未捕获的TransactionInactiveError:无法在“IDBObjectStore”上执行“添加”:事务已完成。
我尝试过使用Firefox和Chrome。
答案 0 :(得分:3)
这是索引数据库的设计点:当事务没有进一步处理请求时,事务会立即尝试提交。可以在创建后直接对事务进行请求,也可以在来自该事务中先前请求的事件的处理程序中进行请求。所以你不能在public ArrayList<String> getFile(File dir) {
File listFile[] = dir.listFiles();
if (listFile != null && listFile.length > 0) {
for (File file : listFile) {
if (file.isDirectory()) {
getFile(file);
}
else {
if (file.getName().endsWith(".png")
|| file.getName().endsWith(".jpg")
|| file.getName().endsWith(".jpeg")
|| file.getName().endsWith(".gif")
|| file.getName().endsWith(".bmp")
|| file.getName().endsWith(".webp"))
{
String temp = file.getPath().substring(0, file.getPath().lastIndexOf('/'));
if (!fileList.contains(temp))
fileList.add(temp);
}
}
}
}
return fileList;
}
回调中做出进一步的请求,因为(1)它不是来自请求的事件处理程序,(2)在你调用setTimeout()
之后没有进一步的工作并且事务将开始试图提交。
这是一个简化的例子,数字表示事物的执行顺序。
setTimeout()
这说明了两种情况:事务在function myFunc(connection) {
var tx = connection.transaction('store');
// (1) transaction is "active" here, you can make requests.
var store = tx.objectStore('store');
store.get('key1').onsuccess = function() {
// (3) transaction is "active" again here.
store.get('key2').onsuccess = function() {
// (5) transaction is also "active" here.
setTimeout(function() {
// (7) transaction is "inactive" here, and the
// transaction will have attempted to commit,
// so this will fail.
store.get('key3'); // WILL THROW
}, 0);
// (6) transaction will be "inactive" when this returns.
// Since there are no more pending requests it will attempt
// to commit.
};
// (4) transaction will be "inactive" when this returns.
};
// (2) transaction will become "inactive" when control
// returns to the event loop here.
}
回调中不活动,并且在事务开始提交之后仍然存在。但是你会分别看到与第一种情况相同的行为 - 例如如果你有一个长期运行的交易(大量的异步请求)并尝试在setTimeout()
中做一些事情,即使有未完成的交易,例如在(3)之后移动setTimeout()
。
您必须先将工作分解为多个事务,或者首先执行所有非IDB异步工作。