Несовместимое взаимодействие между транзакциями IndexedDB и Обещаниями
Я виделсинхронизации обещание размещены на Reddit ивступил в дискуссию с автором, Мы заметили некоторые странные несоответствия в отношениях между транзакциями и обещаниями IndexedDB.
Транзакции IndexedDB автоматически фиксируются, когда всеonsuccess
События заканчиваются. Одним из осложнений является то, что вы не можете делать ничего асинхронного внутриonsuccess
обратный вызов, кроме как сделать другую операцию с той же транзакцией. Например, вы не можете запустить AJAX-запрос вonsuccess
и затем повторно использовать ту же транзакцию после того, как AJAX-запрос вернет некоторые данные.
При чем тут обещания? Насколько я понимаю, разрешение обещаний всегда должно быть асинхронным. Это будет означать, что вы не можете использовать обещания без автоматической фиксации транзакции IndexedDB.
Вот пример того, о чем я говорю:
var openRequest = indexedDB.open("library");
openRequest.onupgradeneeded = function() {
// The database did not previously exist, so create object stores and indexes.
var db = openRequest.result;
var store = db.createObjectStore("books", {keyPath: "isbn"});
var titleIndex = store.createIndex("by_title", "title", {unique: true});
var authorIndex = store.createIndex("by_author", "author");
// Populate with initial data.
store.put({title: "Quarry Memories", author: "Fred", isbn: 123456});
store.put({title: "Water Buffaloes", author: "Fred", isbn: 234567});
store.put({title: "Bedrock Nights", author: "Barney", isbn: 345678});
};
function getByTitle(tx, title) {
return new Promise(function(resolve, reject) {
var store = tx.objectStore("books");
var index = store.index("by_title");
var request = index.get("Bedrock Nights");
request.onsuccess = function() {
var matching = request.result;
if (matching !== undefined) {
// A match was found.
resolve(matching);
} else {
// No match was found.
console.log('no match found');
}
};
});
}
openRequest.onsuccess = function() {
var db = openRequest.result;
var tx = db.transaction("books", "readonly");
getByTitle(tx, "Bedrock Nights").then(function(book) {
console.log('First book', book.isbn, book.title, book.author);
return getByTitle(tx, "Quarry Memories");
}).then(function(book) {
console.log('Second book', book.isbn, book.title, book.author);
// With native promises this gives the error:
// InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable
// With bluebird everything is fine
});
};
(Полное раскрытие: демо было создано Палдепиндом, а не мной!)
Я пробовал это в Chrome и Firefox. В Firefox происходит сбой из-за автоматической фиксации транзакции, но на самом деле он работает в Chrome! Какое поведение правильно? И если поведение Firefox правильное, то буквально невозможно использовать «правильные» реализации обещаний с транзакциями IndexedDB?
Еще одно осложнение: если я загружупевчая птица перед запуском вышеприведенной демонстрации он работает как в Chrome, так и в Firefox. Означает ли это, что синяя птица выполняет обещания синхронно? Я думал, что это не должно было делать это!