异步索引数据库
Asynchronous indexeddb
我想用 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) 时,第二次出现此错误 "add":
Uncaught TransactionInactiveError: Failed to execute 'add' on 'IDBObjectStore': The transaction has finished.
我试过使用 Firefox 和 Chrome。
这是 Indexed DB 的一个设计要点:事务在没有进一步的请求需要处理时尝试立即提交。可以在创建后直接针对事务发出请求,也可以在处理程序中从该事务中先前请求的事件中发出请求。因此,您不能在 setTimeout()
回调中发出进一步的请求,因为 (1) 它不是来自请求的事件处理程序,并且 (2) 在您调用 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()
回调中未处于活动状态,并且无论如何都在事务开始提交之后。但是您会分别看到与第一种情况相同的行为 - 例如如果你有一个长 运行 的交易(很多异步请求)并尝试在 setTimeout()
中做一些事情,即使有未完成的交易,例如在 (3) 之后移动 setTimeout()
。
您必须将您的工作分解为多个事务,或者首先完成所有非 IDB 异步工作。
我想用 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) 时,第二次出现此错误 "add":
Uncaught TransactionInactiveError: Failed to execute 'add' on 'IDBObjectStore': The transaction has finished.
我试过使用 Firefox 和 Chrome。
这是 Indexed DB 的一个设计要点:事务在没有进一步的请求需要处理时尝试立即提交。可以在创建后直接针对事务发出请求,也可以在处理程序中从该事务中先前请求的事件中发出请求。因此,您不能在 setTimeout()
回调中发出进一步的请求,因为 (1) 它不是来自请求的事件处理程序,并且 (2) 在您调用 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()
回调中未处于活动状态,并且无论如何都在事务开始提交之后。但是您会分别看到与第一种情况相同的行为 - 例如如果你有一个长 运行 的交易(很多异步请求)并尝试在 setTimeout()
中做一些事情,即使有未完成的交易,例如在 (3) 之后移动 setTimeout()
。
您必须将您的工作分解为多个事务,或者首先完成所有非 IDB 异步工作。