javascript - 仅在 IndexedDB 中更新对象后运行代码(特别是在 Chrome 中)

标签 javascript google-chrome asynchronous cross-browser indexeddb

我觉得这是一件非常平凡的事情。我想更新 IndexedDB 数据库中的对象,然后运行一些代码,然后使用更新后的值。

我最初所做的只是在调用 cursor.update 后运行我的回调函数,这在 Firefox 中有效。但它在 Chrome 中失败,在运行以下代码之前不会发生更新。这可能是竞争条件,因为(据我了解)更新是异步的。

然后我想我应该使用 cursor.updateonsuccess 信号来调用我的回调函数。但令我惊讶的是,这在 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/

相关文章:

javascript - 如何使用 Angular.js 选择后显示图像

javascript - PHP无限随机数生成器,无需刷新页面

javascript - 使用 CSS 的 jQuery 垂直滑出菜单

javascript - 如何使用 jQuery ui datepicker 计算从今天开始的天数?

google-chrome - img 元素的内容属性

javascript - 为什么浏览器在请求 JavaScript 文件时不发送 cookie?

android - Chrome 报告来自不同计算机的同一站点的 2 种不同的 SSL 挂锁状态,可能受到感染?

linux - Alsa异步回调

http - 响应后异步工作

scala - 是否有更好的 monadic 抽象替代方案来表示长时间运行的异步任务?