Inkonsistentes Zusammenspiel zwischen indexierten DB-Transaktionen und Versprechungen

Ich sah sync-promise gepostet auf Reddit undmit dem Autor diskutieren. Wir haben einige seltsame Inkonsistenzen in der Beziehung zwischen Transaktionen und Versprechungen in IndexedDB festgestellt.

IndexedDB-Transaktionen werden automatisch festgeschrieben, wenn alleonsuccess events beenden. Eine Komplikation ist, dass Sie in einem @ nichts asynchrones machen könnonsuccess Rückruf, außer einen anderen Vorgang für dieselbe Transaktion ausführen. Sie können beispielsweise keine AJAX-Anforderung in einem @ starteonsuccess und verwenden Sie dieselbe Transaktion erneut, nachdem die AJAX-Anforderung einige Daten zurückgegeben hat.

Was haben Versprechen damit zu tun? Wie ich es verstehe, soll die Auflösung von Versprechungen immer asynchron sein. Dies würde bedeuten, dass Sie keine Versprechungen verwenden können, ohne eine IndexedDB-Transaktion automatisch zu bestätigen.

Hier ist ein Beispiel dafür, wovon ich spreche:

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

(Vollständige Offenlegung: Die Demo wurde von paldepind erstellt, nicht von mir!)

Ich habe es in Chrome und Firefox ausprobiert. In Firefox schlägt die automatische Festschreibung der Transaktion fehl, in Chrome funktioniert sie jedoch! Welches Verhalten ist richtig? Und wenn das Verhalten von Firefox korrekt ist, ist es dann buchstäblich unmöglich, "richtige" Versprechungsimplementierungen für Transaktionen mit IndexedDB zu verwenden?

Eine weitere Komplikation: Wenn ich lade bluebird Vor dem Ausführen der obigen Demo funktioniert sie sowohl in Chrome als auch in Firefox. Bedeutet dies, dass Bluebird Versprechen synchron löst? Ich dachte, das hätte ich nicht tun sollen!

JSFiddle

Antworten auf die Frage(6)

Ihre Antwort auf die Frage