我觉得这是一件非常平凡的事情。我想更新 IndexedDB 数据库中的对象,然后运行一些代码,然后使用更新后的值。
我最初所做的只是在调用 cursor.update
后运行我的回调函数,这在 Firefox 中有效。但它在 Chrome 中失败,在运行以下代码之前不会发生更新。这可能是竞争条件,因为(据我了解)更新是异步的。
然后我想我应该使用 cursor.update
的 onsuccess
信号来调用我的回调函数。但令我惊讶的是,这在 Chrome 中似乎也不起作用!
一些示例代码 you can run on jsFiddle... although amusingly this seems to crash in Firefox in jsFiddle for some reason, but Chrome works fine; for Firefox you can run it locally and it works (这会在浏览器的 JavaScript 控制台上产生输出):
<html>
<head>
<script>
var db, request;
request = indexedDB.open("test", 1);
request.onupgradeneeded = function (event) {
var i, leagueStore, teams, teamStore;
db = event.target.result;
objectStore = db.createObjectStore("objects", {keyPath: "id"});
};
request.onsuccess = function (event) {
db = request.result;
// Add some dummy data
db.transaction("objects", "readwrite").objectStore("objects").put({
id: 0,
value: 42
});
// Update data
db.transaction("objects", "readwrite").objectStore("objects").openCursor(0).onsuccess = function (event) {
var cursor, object;
cursor = event.target.result;
object = cursor.value;
object.value = 43;
cursor.update(object).onsuccess = function (event) {
db.transaction("objects").objectStore("objects").get(0).onsuccess = function (event) {
console.log("Cursor update onsuccess event:");
console.log(event.target.result);
};
};
// Read back updated data
db.transaction("objects").objectStore("objects").get(0).onsuccess = function (event) {
console.log("The line after the cursor update:");
console.log(event.target.result);
};
// Wait a little bit, then read it back
setTimeout(function () {
db.transaction("objects").objectStore("objects").get(0).onsuccess = function (event) {
console.log("After an additional delay via setTimeout:");
console.log(event.target.result);
};
}, 100);
};
};
</script>
</head>
</html>
观察到的行为(全部在 Ubuntu 12.10,FWIW 上):
在 Firefox 19(当前稳定版)中,所有三个记录的对象都是相同的,value
设置为 43:
The line after the cursor update:
Object {id: 0, value: 43}
Cursor update onsuccess event:
Object {id: 0, value: 43}
After an additional delay via setTimeout:
Object {id: 0, value: 43}
在 Chrome 25(当前稳定版)和 27(当前不稳定版)中,我通常得到这样的输出:
The line after the cursor update:
Object {id: 0, value: 42}
Cursor update onsuccess event:
Object {id: 0, value: 42}
After an additional delay via setTimeout:
Object {id: 0, value: 43}
有时前两个输出中的一个会更新为 43,但通常是 42。
那么,我的问题又是……更新实际完成后如何运行某些东西? (也就是说,不依赖于 setTimeout
引起的一些可笑的任意延迟。)
替代问题:我做错了什么,还是 Chrome 中的错误?
附带问题:如果有人有 IE 10,我想知道它在这种情况下的表现如何......
最佳答案
您不需要设置超时,只需等待交易完成如下:
// Update data
var tx = db.transaction("objects", "readwrite");
tx.objectStore("objects").openCursor(0).onsuccess = function (event) {
var cursor, object;
cursor = event.target.result;
object = cursor.value;
object.value = 43;
cursor.update(object).onsuccess = function (event) {
db.transaction("objects").objectStore("objects").get(0).onsuccess = function (event) {
console.log("Cursor update onsuccess event:");
console.log(event.target.result);
};
};
};
tx.oncomplete = function() {
// Read back updated data
db.transaction("objects").objectStore("objects").get(0).onsuccess = function (event) {
console.log("The line after the cursor update:");
console.log(event.target.result);
};
}
这是 IndexedDB API 令人困惑的方面之一。 Request onsuccess 并不意味着你的成功被写入了数据库。只有交易完成后才能确认。原因是,您仍然可以在写入请求后中止事务 tx.abort()
。
关于javascript - 仅在 IndexedDB 中更新对象后运行代码(特别是在 Chrome 中),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15151242/