Signatur
Beschreibung
Das Ereignis upgradeneeded tritt auf, wenn indexedDB.open(name, version) mit einer Versionsnummer aufgerufen wird, die höher ist als die aktuell gespeicherte Version, oder wenn die Datenbank noch gar nicht existiert (dann ist oldVersion gleich 0). Das Ereignis ist vom Typ IDBVersionChangeEvent und wird vor success ausgelöst.
Nur in diesem Handler darf das Schema der Datenbank geändert werden: Object Stores mit createObjectStore() anlegen oder mit deleteObjectStore() entfernen und Indizes mit createIndex() bzw. deleteIndex() verwalten. Dafür läuft automatisch eine Transaktion im Modus "versionchange", die über request.transaction erreichbar ist.
Registrieren lässt sich der Handler entweder mit request.addEventListener("upgradeneeded", handler) oder über die Eigenschaft request.onupgradeneeded = handler. Üblich ist ein schrittweises Migrationsmuster: Anhand von event.oldVersion werden nacheinander alle Migrationsschritte bis zur neuen Version ausgeführt, sodass Nutzer mit jedem alten Stand korrekt aktualisiert werden.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Der Ereignisname "upgradeneeded". |
|
| $handler Pflicht | (event: IDBVersionChangeEvent) => void | Callback mit dem Ereignisobjekt. Wichtige Eigenschaften: event.oldVersion (bisherige Version, 0 bei neuer DB), event.newVersion (Zielversion) und event.target.result (die IDBDatabase). |
|
| $options | boolean | AddEventListenerOptions | false | Optionale Listener-Optionen wie once oder signal. |
Rückgabewert
addEventListener gibt nichts zurück. Der Handler bekommt ein IDBVersionChangeEvent übergeben.Beispiele
Datenbank beim ersten Öffnen anlegen (addEventListener)
const request = indexedDB.open('notizen-db', 1);
request.addEventListener('upgradeneeded', (event) => {
const db = event.target.result;
console.log(`Upgrade von ${event.oldVersion} auf ${event.newVersion}`);
// Object Store mit automatischem Schlüssel anlegen
const store = db.createObjectStore('notizen', { keyPath: 'id', autoIncrement: true });
store.createIndex('nachDatum', 'erstelltAm');
});
request.addEventListener('success', () => {
console.log('Datenbank bereit:', request.result.name);
});
request.addEventListener('error', () => {
console.error('Fehler:', request.error);
});
Schrittweise Migration über onupgradeneeded
const request = indexedDB.open('shop-db', 3);
request.onupgradeneeded = (event) => {
const db = request.result;
const tx = request.transaction; // versionchange-Transaktion
// Kein break: jede Stufe baut auf der vorherigen auf
switch (event.oldVersion) {
case 0:
db.createObjectStore('produkte', { keyPath: 'sku' });
case 1:
tx.objectStore('produkte').createIndex('nachPreis', 'preis');
case 2:
db.createObjectStore('warenkorb', { keyPath: 'sku' });
}
console.log('Migration auf Version', event.newVersion, 'fertig');
};
request.onsuccess = () => console.log('Stores:', [...request.result.objectStoreNames]);
Als Promise kapseln und blockierte Upgrades behandeln
const openDB = (name, version, upgrade) =>
new Promise((resolve, reject) => {
const req = indexedDB.open(name, version);
req.onupgradeneeded = (e) => upgrade(req.result, e.oldVersion, req.transaction);
req.onsuccess = () => {
const db = req.result;
// Andere Tabs wollen upgraden: Verbindung freigeben
db.onversionchange = () => db.close();
resolve(db);
};
req.onerror = () => reject(req.error);
req.onblocked = () => console.warn('Upgrade blockiert – bitte andere Tabs schließen');
});
const db = await openDB('app-db', 2, (db, oldVersion) => {
if (oldVersion < 1) db.createObjectStore('einstellungen');
if (oldVersion < 2) db.createObjectStore('cache', { keyPath: 'url' });
});
console.log(db.version);
// Wichtig · Fallstricke
- Schema-Änderungen sind nur hier erlaubt: Ein Aufruf von
createObjectStore()außerhalb einerversionchange-Transaktion wirft eineInvalidStateError-DOMException. - Keine asynchronen Pausen: Wartet man im Handler mit
awaitauf etwas, das nichts mit IndexedDB zu tun hat (z. B.fetch), wird die Transaktion automatisch abgeschlossen und spätere Zugriffe schlagen mitTransactionInactiveErrorfehl. - Die Versionsnummer muss eine positive ganze Zahl sein. Ist die angeforderte Version niedriger als die gespeicherte, wird kein
upgradeneededausgelöst, sondernerrormitVersionError. - Sind in anderen Tabs noch Verbindungen offen, wird zuerst
blockedausgelöst. Deshalb sollte jede Verbindung aufversionchangereagieren unddb.close()aufrufen. - Wirft der Handler eine Ausnahme oder wird die Transaktion abgebrochen, schlägt das Öffnen fehl und die alte Version bleibt erhalten.
- Browser-Unterstützung: in allen modernen Browsern vorhanden. In Web Workern verfügbar. Im privaten Modus älterer Firefox-Versionen war IndexedDB teilweise gesperrt.