Start · Sprachen · JavaScript · Referenz · IDBTransaction.objectStore()

IDBTransaction.objectStore()

Methode

Gibt das <code>IDBObjectStore</code>-Objekt für einen Object Store zurück, der zum Scope der Transaktion gehört, damit man darin lesen und schreiben kann.

seit JavaScript Baseline: alle Browser (IndexedDB 2.0) Kategorie: webapi

Signatur

IDBTransaction.prototype.objectStore(name)

Beschreibung

objectStore() ist in IndexedDB der übliche Weg, um innerhalb einer Transaktion an einen konkreten Object Store zu kommen. Eine Transaktion legt man mit IDBDatabase.transaction(storeNames, mode) an. Dabei bestimmt man den Scope, also die Liste der Stores, auf die die Transaktion zugreifen darf. objectStore(name) liefert dann das IDBObjectStore-Objekt für einen dieser Stores. Über dieses Objekt ruft man Methoden wie get(), put(), add(), delete(), openCursor() oder index() auf.

Der zurückgegebene Store ist fest an die Transaktion gebunden, aus der er stammt. Alle Anfragen über dieses Objekt laufen innerhalb dieser Transaktion und gelten mit dem Zugriffsmodus, der dort festgelegt wurde ("readonly", "readwrite" oder "versionchange"). Ruft man die Methode in derselben Transaktion mehrmals mit demselben Namen auf, bekommt man laut Spezifikation jedes Mal dieselbe IDBObjectStore-Instanz zurück.

Sonderfall upgradeneeded: Während einer versionchange-Transaktion gehören alle Stores der Datenbank zum Scope. Über event.target.transaction.objectStore(name) kommt man dort an bestehende Stores, um zum Beispiel neue Indizes anzulegen oder Daten umzuziehen.

Parameter

Name Typ Default Beschreibung
$name Pflicht string Name des Object Stores, den man haben möchte. Der Store muss zum Scope der Transaktion gehören, also beim Aufruf von IDBDatabase.transaction() angegeben worden sein.

Rückgabewert

Typ
IDBObjectStore
Beschreibung
Ein IDBObjectStore-Objekt, über das man im Kontext dieser Transaktion auf den Store zugreift.

Beispiele

Datensatz in einer readwrite-Transaktion speichern

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

const db = await openDb();
const tx = db.transaction('produkte', 'readwrite');
const store = tx.objectStore('produkte');

store.put({ id: 1, name: 'Tastatur', preis: 49.9 });

tx.oncomplete = () => console.log('Gespeichert');
tx.onerror = () => console.error(tx.error);
Gespeichert

Mehrere Stores in einer Transaktion (atomar)

// Bestellung anlegen und Lagerbestand senken – entweder beides oder nichts
const tx = db.transaction(['bestellungen', 'lager'], 'readwrite');
const bestellungen = tx.objectStore('bestellungen');
const lager = tx.objectStore('lager');

const req = lager.get('artikel-42');
req.onsuccess = () => {
  const eintrag = req.result;
  if (!eintrag || eintrag.menge < 1) {
    tx.abort(); // nichts wird geschrieben
    return;
  }
  eintrag.menge -= 1;
  lager.put(eintrag);
  bestellungen.add({ artikel: 'artikel-42', datum: Date.now() });
};

tx.oncomplete = () => console.log('Bestellung abgeschlossen');
tx.onabort = () => console.warn('Bestellung abgebrochen');
Bestellung abgeschlossen

Index in upgradeneeded auf bestehendem Store anlegen

const req = indexedDB.open('shop', 2);

req.onupgradeneeded = (event) => {
  // Die versionchange-Transaktion umfasst alle Stores
  const tx = event.target.transaction;
  const store = tx.objectStore('produkte');
  if (!store.indexNames.contains('nachName')) {
    store.createIndex('nachName', 'name', { unique: false });
  }
};

req.onsuccess = () => console.log('Upgrade fertig, Version', req.result.version);
Upgrade fertig, Version 2

Fehler bei einem Store außerhalb des Scopes abfangen

const tx = db.transaction('produkte', 'readonly');
try {
  tx.objectStore('kunden'); // nicht im Scope
} catch (err) {
  console.log(err.name);
}
NotFoundError

// Wichtig · Fallstricke

  • NotFoundError (DOMException): Der angeforderte Store gehört nicht zum Scope der Transaktion. Das passiert auch dann, wenn der Store in der Datenbank existiert, bei db.transaction() aber nicht mit angegeben wurde.
  • InvalidStateError: Die Transaktion ist schon abgeschlossen (complete) oder abgebrochen (abort).
  • Automatisches Commit: Eine Transaktion wird automatisch abgeschlossen, sobald keine Anfragen mehr offen sind und die Kontrolle an die Event-Loop zurückgeht. Wer zwischen objectStore() und dem nächsten Request auf etwas anderes wartet (etwa mit await fetch() oder setTimeout), bekommt beim nächsten Zugriff einen TransactionInactiveError. Asynchrone Arbeit deshalb vor oder nach der Transaktion erledigen.
  • Schreibende Methoden wie put(), add() oder delete() werfen in einer "readonly"-Transaktion einen ReadOnlyError.
  • Den Store-Objekten nicht über das Ende der Transaktion hinaus vertrauen: Für jede neue Transaktion muss man objectStore() neu aufrufen.
  • Kompatibilität: Die Methode wird in allen modernen Browsern und in Web Workern unterstützt. In privaten Fenstern mancher Browser ist IndexedDB eingeschränkt oder nur flüchtig verfügbar.