Start · Sprachen · JavaScript · Referenz · Window.indexedDB

Window.indexedDB

Eigenschaft

Schreibgeschützte Eigenschaft, die das <code>IDBFactory</code>-Objekt liefert – den Einstiegspunkt, um IndexedDB-Datenbanken asynchron zu öffnen, zu löschen und zu vergleichen.

seit JavaScript Baseline: alle Browser (seit ca. 2015) Kategorie: webapi

Signatur

get Window.indexedDB

Beschreibung

window.indexedDB gibt ein IDBFactory-Objekt zurück. Darüber öffnen Sie mit open(name, version) eine clientseitige, transaktionale Datenbank. Mit deleteDatabase(name) löschen Sie eine Datenbank, und databases() listet alle vorhandenen Datenbanken des Ursprungs auf. Die Eigenschaft ist auch in Web Workern als self.indexedDB verfügbar (WorkerGlobalScope.indexedDB).

IndexedDB eignet sich für große, strukturierte Datenmengen: Offline-Caches, Entwürfe, Dateien als Blob oder durchsuchbare Datensätze mit Indizes. Anders als localStorage arbeitet die API asynchron und blockiert den Haupt-Thread nicht. Sie speichert beliebige, per Structured Clone kopierbare Werte und unterstützt Transaktionen.

Die API arbeitet ereignisbasiert mit IDBRequest-Objekten und den Ereignissen success, error und upgradeneeded. Das Schema, also Object Stores und Indizes, darf nur im upgradeneeded-Handler angelegt oder geändert werden. Dieser Handler wird ausgelöst, wenn die angeforderte Versionsnummer höher ist als die gespeicherte. In der Praxis verpackt man die Requests oft in Promises oder nutzt eine schlanke Bibliothek wie idb.

Rückgabewert

Typ
IDBFactory
Beschreibung
Das IDBFactory-Objekt des aktuellen Ursprungs. Es bietet die Methoden open(), deleteDatabase(), databases() und cmp().

Beispiele

Datenbank öffnen und Schema anlegen

const request = window.indexedDB.open('notizen-db', 1);

// Nur hier dürfen Object Stores und Indizes angelegt werden
request.onupgradeneeded = (event) => {
  const db = event.target.result;
  const store = db.createObjectStore('notizen', { keyPath: 'id', autoIncrement: true });
  store.createIndex('nachDatum', 'erstellt');
};

request.onsuccess = () => {
  const db = request.result;
  console.log('Geöffnet:', db.name, 'Version', db.version);
};

request.onerror = () => console.error('Fehler:', request.error);
Geöffnet: notizen-db Version 1

Promise-Wrapper mit async/await zum Speichern und Lesen

const openDB = (name, version) => new Promise((resolve, reject) => {
  const req = indexedDB.open(name, version);
  req.onupgradeneeded = () => {
    const db = req.result;
    if (!db.objectStoreNames.contains('notizen')) {
      db.createObjectStore('notizen', { keyPath: 'id', autoIncrement: true });
    }
  };
  req.onsuccess = () => resolve(req.result);
  req.onerror = () => reject(req.error);
});

const promisify = (req) => new Promise((resolve, reject) => {
  req.onsuccess = () => resolve(req.result);
  req.onerror = () => reject(req.error);
});

const main = async () => {
  const db = await openDB('notizen-db', 1);
  const tx = db.transaction('notizen', 'readwrite');
  const store = tx.objectStore('notizen');
  const id = await promisify(store.add({ text: 'Einkaufen', erstellt: Date.now() }));
  const notiz = await promisify(store.get(id));
  console.log(notiz.text);
  db.close();
};

main();
Einkaufen

Unterstützung prüfen, Datenbanken auflisten und löschen

const aufraeumen = async () => {
  if (!('indexedDB' in window)) {
    console.warn('IndexedDB wird nicht unterstützt');
    return;
  }
  // databases() gibt es noch nicht in allen Browsern
  if (indexedDB.databases) {
    const liste = await indexedDB.databases();
    console.log(liste.map((d) => `${d.name} (v${d.version})`));
  }
  const del = indexedDB.deleteDatabase('notizen-db');
  del.onsuccess = () => console.log('Datenbank gelöscht');
  del.onblocked = () => console.warn('Löschen blockiert – andere Tabs haben die DB noch offen');
};

aufraeumen();
["notizen-db (v1)"] Datenbank gelöscht

// Wichtig · Fallstricke

  • Versionierung: Die Version muss eine positive Ganzzahl sein. Eine niedrigere Version als die gespeicherte führt zu einem VersionError. Sind in anderen Tabs noch Verbindungen offen, wird blocked ausgelöst. Deshalb im versionchange-Handler db.close() aufrufen.
  • Transaktionen schließen sich automatisch, sobald keine Anfragen mehr ausstehen. Wer zwischen zwei Anfragen auf etwas Fremdes wartet, etwa mit await fetch(), bekommt einen TransactionInactiveError.
  • Speicherort und Kontingent: Die Daten gehören zum Ursprung (Same-Origin) und unterliegen Speicherkontingenten. Der Browser kann sie bei Speicherknappheit löschen. Mit navigator.storage.persist() lässt sich dauerhafte Speicherung anfordern.
  • Privater Modus und Einschränkungen: In manchen Browsern oder Kontexten (ältere Firefox-Versionen im privaten Modus, gesperrte Drittanbieter-Cookies in iframes) schlägt open() fehl oder indexedDB ist null. Eine Fehlerbehandlung ist also Pflicht.
  • Sicherheit: IndexedDB ist nicht verschlüsselt. Keine sensiblen Daten wie Tokens oder Passwörter unverschlüsselt ablegen, denn jedes Skript auf demselben Ursprung kann darauf zugreifen, bei einer XSS-Lücke also auch eingeschleuster Code.
  • indexedDB.databases() wird erst seit Firefox 126 unterstützt. Präfixe wie webkitIndexedDB und mozIndexedDB sind veraltet.