Start · Sprachen · JavaScript · Referenz · IDBRequest

IDBRequest

Schnittstelle

Stellt eine asynchrone IndexedDB-Anfrage dar, deren Ergebnis oder Fehler über die Events <code>success</code> und <code>error</code> bzw. die Eigenschaften <code>result</code> und <code>error</code> abrufbar ist.

seit JavaScript Baseline: alle Browser (IndexedDB 2.0, seit 2015 w Kategorie: webapi

Signatur

interface IDBRequest extends EventTarget

Beschreibung

Jede Operation in IndexedDB läuft asynchron ab. Methoden wie IDBObjectStore.get(), put(), add(), delete(), openCursor() oder IDBIndex.getAll() geben kein Ergebnis direkt zurück, sondern ein IDBRequest-Objekt. Über dieses Objekt erfährt man, wann die Operation fertig ist und ob sie geklappt hat. Den Ausgang meldet der Browser über die Events success und error.

Wichtige Eigenschaften:

  • result: Ergebnis der Anfrage, z. B. der gelesene Datensatz, der Schlüssel oder ein Cursor. Solange die Anfrage läuft, führt ein Zugriff zu einer InvalidStateError-DOMException.
  • error: Eine DOMException bei einem Fehlschlag, sonst null.
  • readyState: "pending" oder "done".
  • source: Das Objekt, von dem die Anfrage ausging (IDBObjectStore, IDBIndex, IDBCursor oder null).
  • transaction: Die IDBTransaction, zu der die Anfrage gehört (beim Öffnen einer Datenbank außerhalb von upgradeneeded ist der Wert null).
  • onsuccess / onerror: Event-Handler-Eigenschaften, alternativ zu addEventListener().

Der Untertyp IDBOpenDBRequest, den indexedDB.open() zurückgibt, erweitert IDBRequest um die Events upgradeneeded und blocked. In modernem Code verpackt man ein IDBRequest meist in ein Promise, damit sich async/await nutzen lässt.

Rückgabewert

Typ
IDBRequest
Beschreibung
Instanzen gibt es nicht über einen Konstruktor. Sie werden von IndexedDB-Methoden wie IDBObjectStore.get() oder IDBIndex.openCursor() zurückgegeben.

Beispiele

Datenbank öffnen und einen Datensatz lesen (onsuccess/onerror)

const openReq = indexedDB.open('shop', 1);

openReq.onupgradeneeded = () => {
  const db = openReq.result;
  const store = db.createObjectStore('produkte', { keyPath: 'id' });
  store.add({ id: 1, name: 'Tastatur', preis: 49.9 });
};

openReq.onsuccess = () => {
  const db = openReq.result;
  const tx = db.transaction('produkte', 'readonly');
  const request = tx.objectStore('produkte').get(1); // IDBRequest

  console.log(request.readyState); // "pending"

  request.onsuccess = () => {
    console.log(request.readyState, request.result);
  };
  request.onerror = () => {
    console.error('Lesefehler:', request.error);
  };
};
pending done { id: 1, name: 'Tastatur', preis: 49.9 }

IDBRequest in ein Promise verpacken (async/await)

const promisify = (request) =>
  new Promise((resolve, reject) => {
    request.addEventListener('success', () => resolve(request.result));
    request.addEventListener('error', () => reject(request.error));
  });

const speichern = async () => {
  const db = await promisify(indexedDB.open('shop', 1));
  const store = db.transaction('produkte', 'readwrite').objectStore('produkte');

  const key = await promisify(store.put({ id: 2, name: 'Maus', preis: 19.9 }));
  console.log('Gespeichert unter Schlüssel', key);

  const alle = await promisify(store.getAll());
  console.log(alle.length, 'Produkte');
};

speichern().catch(console.error);
Gespeichert unter Schlüssel 2 2 Produkte

Cursor-Request: mehrfaches success-Event

const req = indexedDB.open('shop', 1);
req.onsuccess = () => {
  const store = req.result.transaction('produkte').objectStore('produkte');
  const cursorReq = store.openCursor();

  // success feuert für JEDEN Datensatz erneut
  cursorReq.onsuccess = () => {
    const cursor = cursorReq.result;
    if (cursor) {
      console.log(cursor.key, cursor.value.name, cursorReq.source === store);
      cursor.continue();
    } else {
      console.log('Fertig');
    }
  };
};
1 Tastatur true 2 Maus true Fertig

Fehler abfangen und Transaktionsabbruch verhindern

const req = indexedDB.open('shop', 1);
req.onsuccess = () => {
  const tx = req.result.transaction('produkte', 'readwrite');
  const addReq = tx.objectStore('produkte').add({ id: 1, name: 'Duplikat' });

  addReq.onerror = (event) => {
    console.warn(addReq.error.name); // ConstraintError
    event.preventDefault();  // Transaktion NICHT abbrechen
    event.stopPropagation(); // nicht zu tx/db weiterleiten
  };
  tx.oncomplete = () => console.log('Transaktion abgeschlossen');
};
ConstraintError Transaktion abgeschlossen

// Wichtig · Fallstricke

  • result zu früh gelesen: Liest man result oder error, solange readyState noch "pending" ist, wirft das eine InvalidStateError-DOMException. Greif erst im success- bzw. error-Handler darauf zu.
  • Fehler bricht die Transaktion ab: Ein error-Event steigt vom Request über die IDBTransaction bis zur IDBDatabase auf. Ohne event.preventDefault() wird die ganze Transaktion zurückgerollt.
  • Transaktionen schließen sich selbst: Eine Transaktion wird beendet, sobald keine Anfragen mehr offen sind. Wer zwischen zwei Requests auf ein anderes await wartet (z. B. auf fetch()), bekommt danach einen TransactionInactiveError. Innerhalb einer Transaktion sollten daher nur IndexedDB-Requests abgewartet werden.
  • Erfolgreicher Request heißt nicht gespeichert: Ein success-Event bei put()/add() garantiert noch nicht, dass die Daten dauerhaft geschrieben sind. Darauf ist erst beim complete-Event der Transaktion Verlass.
  • Cursor: Bei openCursor() wird dasselbe Request-Objekt nach jedem continue() wiederverwendet, und success feuert mehrfach.
  • Kompatibilität: Wird von allen modernen Browsern, in Web Workern und in Service Workern unterstützt. Im privaten Modus älterer Safari- und Firefox-Versionen war IndexedDB eingeschränkt oder nicht verfügbar. Für eine Promise-API empfiehlt sich die kleine Bibliothek idb.