Start · Sprachen · JavaScript · Referenz · IDBCursor.update()

IDBCursor.update()

Methode

Ersetzt den Datensatz an der aktuellen Cursor-Position im Objekt-Store durch einen neuen Wert und gibt ein <code>IDBRequest</code> zurück.

seit JavaScript Baseline: alle modernen Browser (IndexedDB 1.0) Kategorie: webapi

Signatur

IDBCursor.prototype.update(value)

Beschreibung

Mit update() überschreiben Sie den Datensatz, auf dem ein IDBCursor gerade steht. Die Methode arbeitet asynchron: Sie gibt sofort ein IDBRequest zurück, und das Ergebnis kommt später über dessen Ereignisse success oder error. Bei Erfolg enthält request.result den Schlüssel des aktualisierten Datensatzes.

Typischerweise nutzen Sie update() für Massenänderungen: Sie laufen mit openCursor() über einen Objekt-Store oder Index, prüfen oder verändern jeden Datensatz und schreiben ihn direkt zurück. So müssen Sie nicht erst alle Datensätze laden und danach einzeln mit put() speichern.

Voraussetzungen: Die Transaktion muss im Modus "readwrite" geöffnet sein. Der Cursor muss mit openCursor() erzeugt worden sein, nicht mit openKeyCursor(). Er muss außerdem gerade auf einem Datensatz stehen. Verwendet der Store Inline-Schlüssel (keyPath), darf sich der Primärschlüssel im neuen Wert nicht ändern.

Parameter

Name Typ Default Beschreibung
$value Pflicht any Der neue Wert für die aktuelle Cursor-Position. Er muss mit dem structured clone-Algorithmus kopierbar sein. Bei Inline-Schlüsseln muss der Schlüssel im Wert gleich bleiben.

Rückgabewert

Typ
IDBRequest<IDBValidKey>
Beschreibung
Ein IDBRequest. Bei Erfolg enthält result den Primärschlüssel des aktualisierten Datensatzes.

Beispiele

Alle Artikel einer Kategorie um 10 % verteuern

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

request.onsuccess = () => {
  const db = request.result;
  const tx = db.transaction('produkte', 'readwrite');
  const store = tx.objectStore('produkte');

  store.openCursor().onsuccess = (event) => {
    const cursor = event.target.result;
    if (!cursor) return; // Keine weiteren Datensätze

    const produkt = cursor.value;
    if (produkt.kategorie === 'buecher') {
      produkt.preis = Math.round(produkt.preis * 1.1 * 100) / 100;
      const upd = cursor.update(produkt);
      upd.onsuccess = () => console.log('Aktualisiert:', upd.result);
    }
    cursor.continue();
  };

  tx.oncomplete = () => console.log('Alle Preise angepasst');
};
Aktualisiert: 3 Aktualisiert: 7 Alle Preise angepasst

Promise-Wrapper mit async/await

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

const markiereAlleGelesen = (db) => new Promise((resolve, reject) => {
  const tx = db.transaction('nachrichten', 'readwrite');
  const index = tx.objectStore('nachrichten').index('gelesen');
  let anzahl = 0;

  // Nur ungelesene Nachrichten (gelesen === 0)
  index.openCursor(IDBKeyRange.only(0)).onsuccess = (e) => {
    const cursor = e.target.result;
    if (!cursor) return;
    promisify(cursor.update({ ...cursor.value, gelesen: 1 }))
      .then(() => anzahl++);
    cursor.continue();
  };

  tx.oncomplete = () => resolve(anzahl);
  tx.onerror = () => reject(tx.error);
});

// Aufruf: const n = await markiereAlleGelesen(db);
// console.log(`${n} Nachrichten als gelesen markiert`);
5 Nachrichten als gelesen markiert

Fehlerbehandlung bei geändertem Schlüssel

store.openCursor().onsuccess = (event) => {
  const cursor = event.target.result;
  if (!cursor) return;
  try {
    // Store hat keyPath 'id' – Änderung des Schlüssels ist verboten
    cursor.update({ ...cursor.value, id: cursor.value.id + 1000 });
  } catch (err) {
    console.error(err.name); // DataError
  }
  cursor.continue();
};
DataError

// Wichtig · Fallstricke

  • Synchron ausgelöste Ausnahmen (sie kommen nicht über onerror): TransactionInactiveError, wenn die Transaktion nicht mehr aktiv ist; ReadOnlyError bei einer "readonly"-Transaktion; InvalidStateError bei einem Schlüssel-Cursor (openKeyCursor()), bei gelöschtem Store oder wenn der Cursor gerade iteriert oder am Ende steht; DataError, wenn sich bei Inline-Schlüsseln der Primärschlüssel ändert; DataCloneError bei nicht klonbaren Werten wie Funktionen oder DOM-Knoten.
  • Transaktion nicht verlieren: Warten Sie zwischen update() und continue() nicht auf fremde Promises wie fetch oder setTimeout. Die Transaktion schließt sich automatisch, sobald keine offenen Anfragen mehr bestehen. Danach werfen weitere Aufrufe TransactionInactiveError.
  • Rufen Sie update() auf, bevor Sie continue() oder advance() aufrufen. Danach steht der Cursor nicht mehr auf dem Datensatz.
  • Ändert update() einen Wert, der für einen laufenden Index-Cursor relevant ist, wird der Datensatz im Index neu einsortiert. Er kann dann erneut besucht werden, wenn er in Laufrichtung nach vorn wandert.
  • Wird nur ein bekannter Datensatz geändert, ist IDBObjectStore.put() einfacher. update() lohnt sich beim Durchlaufen vieler Datensätze.
  • Kompatibilität: Die Methode wird von allen modernen Browsern und in Web Workern unterstützt. Im privaten Modus älterer Safari-Versionen war IndexedDB eingeschränkt.