Start · Sprachen · JavaScript · Referenz · IDBOpenDBRequest: upgradeneeded

IDBOpenDBRequest: upgradeneeded

Ereignis

Wird an einem <code>IDBOpenDBRequest</code> ausgelöst, wenn eine Datenbank neu angelegt oder mit einer höheren Versionsnummer als der gespeicherten geöffnet wird.

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

Signatur

request.addEventListener("upgradeneeded", handler)

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

Typ
void
Beschreibung
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);
});
Upgrade von 0 auf 1 Datenbank bereit: notizen-db

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]);
Migration auf Version 3 fertig Stores: ["produkte", "warenkorb"]

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);
2

// Wichtig · Fallstricke

  • Schema-Änderungen sind nur hier erlaubt: Ein Aufruf von createObjectStore() außerhalb einer versionchange-Transaktion wirft eine InvalidStateError-DOMException.
  • Keine asynchronen Pausen: Wartet man im Handler mit await auf etwas, das nichts mit IndexedDB zu tun hat (z. B. fetch), wird die Transaktion automatisch abgeschlossen und spätere Zugriffe schlagen mit TransactionInactiveError fehl.
  • Die Versionsnummer muss eine positive ganze Zahl sein. Ist die angeforderte Version niedriger als die gespeicherte, wird kein upgradeneeded ausgelöst, sondern error mit VersionError.
  • Sind in anderen Tabs noch Verbindungen offen, wird zuerst blocked ausgelöst. Deshalb sollte jede Verbindung auf versionchange reagieren und db.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.