Signatur
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);
};
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`);
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);
}
// Wichtig · Fallstricke
- Automatischer Commit: Warten Sie innerhalb einer Transaktion nicht auf andere asynchrone Vorgänge (z. B.
await fetch()odersetTimeout). Ist keine Anfrage mehr offen, wird die Transaktion abgeschlossen, und spätere Zugriffe werfen einenTransactionInactiveError. Holen Sie die Daten also vorher. NotFoundErrorwird geworfen, wenn ein angegebener Store nicht existiert.InvalidAccessErrorkommt bei einer leeren Store-Liste,TypeErrorbei einem ungültigenmode.InvalidStateErrortritt auf, wenn die Methode auf einer geschlossenen Verbindung (db.close()) aufgerufen wird oder solange noch eineversionchange-Transaktion läuft (z. B. inonupgradeneeded).- Das Ereignis
successeiner einzelnen Anfrage bedeutet nicht, dass die Daten dauerhaft gespeichert sind. Maßgeblich ist erstcompleteder Transaktion. - Große
readwrite-Bereiche blockieren andere Transaktionen. Halten Sie Geltungsbereich und Laufzeit klein. - Die Option
durabilityund die Methodecommit()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.