Start · Sprachen · JavaScript · Referenz · IDBDatabase.transaction()

IDBDatabase.transaction()

Methode

Startet eine neue Transaktion über einen oder mehrere Objekt-Stores und gibt sofort ein <code>IDBTransaction</code>-Objekt zurück.

seit JavaScript Baseline: alle Browser (options.durability ab Chro Kategorie: webapi

Signatur

IDBDatabase.prototype.transaction(storeNames, mode, options)

Beschreibung

IDBDatabase.transaction() ist der Einstieg für jeden Lese- oder Schreibzugriff auf Daten in IndexedDB. Die Methode legt eine neue IDBTransaction an, die auf die angegebenen Objekt-Stores begrenzt ist. Über transaction.objectStore(name) bekommen Sie dann ein IDBObjectStore, auf dem Sie get(), put(), add(), delete() oder Cursor-Operationen ausführen.

Der Modus legt fest, was erlaubt ist: "readonly" (Standard) nur für Lesezugriffe, "readwrite" zum Ändern von Daten. Mehrere readonly-Transaktionen dürfen parallel laufen, readwrite-Transaktionen mit überlappendem Geltungsbereich werden dagegen nacheinander ausgeführt. Deklarieren Sie deshalb nur die Stores, die Sie wirklich brauchen, und verwenden Sie readwrite nur, wenn Sie tatsächlich schreiben.

Transaktionen werden automatisch abgeschlossen (Commit), sobald keine Anfragen mehr offen sind und die Kontrolle an die Ereignisschleife zurückgeht. Den Abschluss erkennen Sie am Ereignis complete, Fehler an error bzw. abort. Mit transaction.commit() lässt sich der Commit auch ausdrücklich anstoßen, mit abort() machen Sie alle Änderungen rückgängig.

Über options.durability geben Sie an, wie der Browser zwischen Leistung und Ausfallsicherheit abwägen soll: "strict" wartet, bis die Daten auf dem Datenträger sind, "relaxed" meldet den Abschluss früher, "default" überlässt die Wahl dem Browser.

Parameter

Name Typ Default Beschreibung
$storeNames Pflicht string | string[] Name eines Objekt-Stores oder ein Array mit Namen, die zum Geltungsbereich der Transaktion gehören. Auch eine DOMStringList (z. B. db.objectStoreNames) ist erlaubt.
$mode "readonly" | "readwrite" "readonly" Zugriffsmodus. "versionchange" ist hier nicht erlaubt; solche Transaktionen entstehen nur innerhalb von upgradeneeded.
$options { durability?: "default" | "strict" | "relaxed" } { durability: "default" } Zusätzliche Einstellungen. durability steuert, wie stark der Commit abgesichert wird.

Beispiele

Datensatz lesen (readonly)

const openDb = () => new Promise((resolve, reject) => {
  const req = indexedDB.open('shop', 1);
  req.onupgradeneeded = () => {
    req.result.createObjectStore('products', { keyPath: 'id' });
  };
  req.onsuccess = () => resolve(req.result);
  req.onerror = () => reject(req.error);
});

const db = await openDb();
const tx = db.transaction('products'); // Standard: readonly
const request = tx.objectStore('products').get(42);

request.onsuccess = () => {
  console.log('Produkt:', request.result);
};
Produkt: undefined // bzw. das gespeicherte Objekt

Mehrere Datensätze schreiben und auf den Abschluss warten

const saveProducts = (db, products) => new Promise((resolve, reject) => {
  const tx = db.transaction('products', 'readwrite');
  const store = tx.objectStore('products');

  for (const p of products) store.put(p);

  // Erst 'complete' garantiert, dass alles gespeichert ist
  tx.oncomplete = () => resolve(products.length);
  tx.onerror = () => reject(tx.error);
  tx.onabort = () => reject(tx.error ?? new Error('Transaktion abgebrochen'));
});

const count = await saveProducts(db, [
  { id: 1, name: 'Tastatur', price: 49 },
  { id: 2, name: 'Maus', price: 19 }
]);
console.log(`${count} Produkte gespeichert`);
2 Produkte gespeichert

Atomare Buchung über zwei Stores mit durability

const placeOrder = (db, order) => new Promise((resolve, reject) => {
  const tx = db.transaction(['orders', 'products'], 'readwrite', {
    durability: 'strict'
  });
  const products = tx.objectStore('products');
  const orders = tx.objectStore('orders');

  const getReq = products.get(order.productId);
  getReq.onsuccess = () => {
    const product = getReq.result;
    if (!product || product.stock < order.qty) {
      tx.abort(); // alle Änderungen verwerfen
      return;
    }
    product.stock -= order.qty;
    products.put(product);
    orders.add(order);
  };

  tx.oncomplete = () => resolve('Bestellung gebucht');
  tx.onabort = () => reject(new Error('Nicht genug Lagerbestand'));
});

try {
  console.log(await placeOrder(db, { id: 'A-1', productId: 1, qty: 2 }));
} catch (e) {
  console.error(e.message);
}
Bestellung gebucht

// Wichtig · Fallstricke

  • Automatischer Commit: Warten Sie innerhalb einer Transaktion nicht auf andere asynchrone Vorgänge (z. B. await fetch() oder setTimeout). Ist keine Anfrage mehr offen, wird die Transaktion abgeschlossen, und spätere Zugriffe werfen einen TransactionInactiveError. Holen Sie die Daten also vorher.
  • NotFoundError wird geworfen, wenn ein angegebener Store nicht existiert. InvalidAccessError kommt bei einer leeren Store-Liste, TypeError bei einem ungültigen mode.
  • InvalidStateError tritt auf, wenn die Methode auf einer geschlossenen Verbindung (db.close()) aufgerufen wird oder solange noch eine versionchange-Transaktion läuft (z. B. in onupgradeneeded).
  • Das Ereignis success einer einzelnen Anfrage bedeutet nicht, dass die Daten dauerhaft gespeichert sind. Maßgeblich ist erst complete der Transaktion.
  • Große readwrite-Bereiche blockieren andere Transaktionen. Halten Sie Geltungsbereich und Laufzeit klein.
  • Die Option durability und die Methode commit() sind neuer als der Rest der API. Ältere Browser ignorieren das Optionsobjekt.
  • Im privaten Modus mancher Browser ist IndexedDB eingeschränkt oder nur flüchtig verfügbar.