Signatur
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
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);
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();
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();
// 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, wirdblockedausgelöst. Deshalb imversionchange-Handlerdb.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 einenTransactionInactiveError. - 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 oderindexedDBistnull. 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 wiewebkitIndexedDBundmozIndexedDBsind veraltet.