Запуск кода только после обновления объекта в IndexedDB (особенно в Chrome)
Я чувствую, что это довольно обыденная вещь. Я хочу обновить объект в базе данных IndexedDB, а затем запустить некоторый код, после которого используются обновленные значения.
То, что я первоначально сделал, это просто запустил мою функцию обратного вызова после вызоваcursor.update
, который работает в Firefox. Но в Chrome происходит сбой, обновление не происходит до запуска следующего кода. Это, скорее всего, условие гонки, поскольку (насколько я понимаю) обновления являются асинхронными.
Итак, я подумал, что я должен использоватьonsuccess
сигнал оcursor.update
чтобы вызвать мою функцию обратного вызова. Но, к моему большому удивлению, в Chrome это тоже не работает!
Пример кода, которыйвы можете запустить на jsFiddle ... хотя забавно, что по какой-то причине в Firefox происходит сбой в jsFiddle, но Chrome работает нормально; для Firefox вы можете запустить его локально, и он работает (это выводит на консоль 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, мне интересно, как он себя ведет в этой ситуации ..