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

Javascript 仅在IndexedDB(特别是Chrome)中更新对象后运行代码,javascript,google-chrome,asynchronous,cross-browser,indexeddb,Javascript,Google Chrome,Asynchronous,Cross Browser,Indexeddb,我觉得这是一件很平常的事。我想更新IndexedDB数据库中的一个对象,然后运行一些代码,然后使用更新后的值 我最初所做的只是在调用在Firefox中工作的cursor.update后运行回调函数。但是它在Chrome中失败了,在运行下面的代码之前更新不会发生。这可能是一种竞争条件,因为(据我所知)更新是异步的 因此,我认为应该使用cursor.update的onsuccess信号调用回调函数。但令我惊讶的是,这在Chrome中似乎也不起作用 一些示例代码(在浏览器的JavaScript控制台上

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

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

因此,我认为应该使用
cursor.update的
onsuccess
信号调用回调函数。但令我惊讶的是,这在Chrome中似乎也不起作用

一些示例代码(在浏览器的JavaScript控制台上生成输出):

在Chrome 25(当前稳定版本)和Chrome 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中的一个bug


附带问题:如果有人拥有IE10,我想知道它在这种情况下的表现。

我使用promise模式来避免settimeout,并统一数据访问和隐藏游标API。 包含库(include.jaydata.org/jaydata.min.js)后,代码段如下所示():


代码要少得多,您只需更改提供程序的类型即可更改为WebSQL:)

您不需要设置超时,只需等待事务完成,如下所示:

// 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令人困惑的方面之一。请求成功并不意味着您的成功被写入数据库。只有交易完成后才能确认。原因是,在写入请求后,您仍然可以中止事务
tx.abort()

谢谢。那么一个辅助问题。。更新的onsuccess信号有任何用途吗?或者它只是为了迷惑我?我想这是一个Chrome bug。(或者在过去8年中,规范有所改进?)。根据(特别是§2.7.2中的最后一点),更新事务应在后两个读取事务开始之前完成(并且应触发onsuccess事件,并应存储更新的数据)。
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}
$data.Entity.extend("Todo", {
    Id: { type: "int", key: true, computed: true },
    Task: { type: String, required: true, maxLength: 200 }
});

$data.EntityContext.extend("TodoDatabase", {
    Todos: { type: $data.EntitySet, elementType: Todo }
});

var todoDB = new TodoDatabase({ 
    provider: 'indexedDb', databaseName: 'MyTodoDatabase'
});

todoDB.onReady(function() {
    var newTodo = new Todo({Task: "alma"});
    todoDB.Todos.add(newTodo);
    todoDB.saveChanges()
    .then(function() {
        console.log("Initial value: ", newTodo.Task);
        todoDB.Todos.attach(newTodo);
        newTodo.Task = "korte";
        return todoDB.Todos.saveChanges();
    })
    .then(function(){
        console.log("Updated value: ", newTodo.Task);
        return todoDB.Todos
        .filter(function(t) {return t.Id == item.Id;}, {item: newTodo})
        .toArray(function(dbResult){
            var todoFromDb = dbResult[0];
            console.log("Value from DB: ", todoFromDb.Task);
        });
    })


});
// 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);
   };
 }