Interação inconsistente entre transações e promessas do IndexedDB

eu vipromessa de sincronização postado no Reddit eentrou em uma discussão com o autor. Percebemos algumas inconsistências estranhas no relacionamento entre transações e promessas do IndexedDB.

As transações do IndexedDB são confirmadas automaticamente quando todas asonsuccess eventos terminados. Uma complicação é que você não pode fazer nada assíncrono dentro de umonsuccess retorno de chamada, exceto fazer outra operação na mesma transação. Por exemplo, você não pode iniciar uma solicitação AJAX em umonsuccess e reutilize a mesma transação depois que a solicitação AJAX retornar alguns dados.

O que as promessas têm a ver com isso? Pelo que entendi, a resolução da promessa deve sempre ser assíncrona. Isso implica que você não pode usar promessas sem confirmar automaticamente uma transação do IndexedDB.

Aqui está um exemplo do que estou falando:

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

(Divulgação completa: a demo foi criada por paldepind, não por mim!)

Eu tentei no Chrome e Firefox. Ele falha no Firefox devido à confirmação automática da transação, mas na verdade funciona no Chrome! Qual comportamento está correto? E se o comportamento do Firefox estiver correto, é literalmente impossível usar implementações de promessa "corretas" com transações do IndexedDB?

Outra complicação: se eu carregarpássaro azul Antes de executar a demonstração acima, ela funciona no Chrome e no Firefox. Isso significa que o bluebird está resolvendo promessas de forma síncrona? Eu pensei que não era para fazer isso!

JSFiddle

questionAnswers(3)

yourAnswerToTheQuestion