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

IDBCursor.delete()

Methode

Löscht asynchron den Datensatz an der aktuellen Cursor-Position und gibt ein <code>IDBRequest</code> zurück. Die Position des Cursors bleibt dabei unverändert.

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

Signatur

IDBCursor.prototype.delete()

Beschreibung

Mit IDBCursor.delete() entfernen Sie den Datensatz, auf den ein Cursor gerade zeigt, direkt aus dem zugrunde liegenden Object Store. Das ist praktisch, wenn Sie beim Durchlaufen einer Datenmenge anhand einer Bedingung selektiv löschen wollen, z. B. abgelaufene Cache-Einträge oder erledigte Aufgaben. Sie müssen dazu weder den Schlüssel kennen noch IDBObjectStore.delete() separat aufrufen.

Die Methode liefert sofort ein IDBRequest-Objekt zurück. Der eigentliche Löschvorgang läuft asynchron. Ist er erfolgreich, wird das success-Ereignis ausgelöst und request.result ist undefined. Der Cursor bleibt an seiner Position. Um zum nächsten Datensatz zu gelangen, rufen Sie wie gewohnt cursor.continue() oder cursor.advance() auf.

Voraussetzung ist eine Transaktion im Modus "readwrite". Außerdem muss der Cursor ein Wert-Cursor sein. Er muss also mit openCursor() geöffnet worden sein, nicht mit openKeyCursor(). Cursor über einen Index (IDBIndex.openCursor()) sind erlaubt: Gelöscht wird dann der referenzierte Datensatz im Object Store.

Wenn Sie viele Datensätze anhand eines Schlüsselbereichs löschen wollen, ist IDBObjectStore.delete(keyRange) meist deutlich schneller. cursor.delete() lohnt sich vor allem, wenn die Entscheidung vom Inhalt des Datensatzes abhängt.

Rückgabewert

Typ
IDBRequest<undefined>
Beschreibung
Ein IDBRequest, dessen success-Ereignis nach dem erfolgreichen Löschen ausgelöst wird. request.result ist dann undefined. Schlägt der Vorgang fehl, wird error ausgelöst.

Beispiele

Erledigte Aufgaben beim Durchlaufen löschen

const openReq = indexedDB.open('todo-db', 1);

openReq.onupgradeneeded = () => {
  const db = openReq.result;
  const store = db.createObjectStore('todos', { keyPath: 'id', autoIncrement: true });
  store.add({ title: 'Einkaufen', done: true });
  store.add({ title: 'Steuer', done: false });
  store.add({ title: 'Sport', done: true });
};

openReq.onsuccess = () => {
  const db = openReq.result;
  const tx = db.transaction('todos', 'readwrite');
  const store = tx.objectStore('todos');
  let deleted = 0;

  store.openCursor().onsuccess = (event) => {
    const cursor = event.target.result;
    if (!cursor) return; // Ende erreicht

    if (cursor.value.done) {
      const delReq = cursor.delete();
      delReq.onsuccess = () => {
        deleted++;
        console.log(`Gelöscht: ${cursor.value.title}`);
      };
    }
    cursor.continue();
  };

  tx.oncomplete = () => console.log(`Fertig, ${deleted} Einträge entfernt`);
};
Gelöscht: Einkaufen Gelöscht: Sport Fertig, 2 Einträge entfernt

Abgelaufene Cache-Einträge mit Promise-Wrapper entfernen

// Hilfsfunktion: löscht alle Einträge, deren expires in der Vergangenheit liegt
const purgeExpired = (db) => new Promise((resolve, reject) => {
  const tx = db.transaction('cache', 'readwrite');
  const now = Date.now();
  let count = 0;

  tx.objectStore('cache').openCursor().onsuccess = ({ target }) => {
    const cursor = target.result;
    if (!cursor) return;
    if (cursor.value.expires < now) {
      cursor.delete();
      count++;
    }
    cursor.continue();
  };

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

// Nutzung
const db = await new Promise((res, rej) => {
  const r = indexedDB.open('app-cache', 1);
  r.onupgradeneeded = () => r.result.createObjectStore('cache', { keyPath: 'url' });
  r.onsuccess = () => res(r.result);
  r.onerror = () => rej(r.error);
});

const removed = await purgeExpired(db);
console.log(`${removed} abgelaufene Einträge gelöscht`);
0 abgelaufene Einträge gelöscht

Löschen über einen Index-Cursor

// Löscht alle Benutzer mit status 'inactive' über einen Index
const deleteInactive = (db) => {
  const tx = db.transaction('users', 'readwrite');
  const index = tx.objectStore('users').index('by_status');

  index.openCursor(IDBKeyRange.only('inactive')).onsuccess = ({ target }) => {
    const cursor = target.result;
    if (!cursor) return;
    console.log('Entferne Benutzer', cursor.primaryKey);
    cursor.delete(); // löscht den Datensatz im Object Store
    cursor.continue();
  };

  return new Promise((resolve) => { tx.oncomplete = resolve; });
};

// Wichtig · Fallstricke

  • ReadOnlyError: wird ausgelöst, wenn die Transaktion nur im Modus "readonly" läuft. Öffnen Sie sie mit "readwrite".
  • InvalidStateError: wird ausgelöst, wenn der Cursor mit openKeyCursor() erzeugt wurde (Schlüssel-Cursor), wenn er gerade iteriert (also nach continue(), aber vor dem nächsten success) oder wenn er bereits über das Ende hinaus gelaufen ist.
  • TransactionInactiveError: Die Transaktion ist nicht mehr aktiv. Das passiert oft, wenn Sie zwischen zwei Cursor-Schritten mit await auf etwas anderes warten, etwa auf fetch. IndexedDB schließt Transaktionen automatisch, sobald keine Anfragen mehr offen sind.
  • Nach delete() gibt cursor.value weiterhin den alten Wert zurück. Der Cursor zeigt noch auf die Position des gelöschten Datensatzes.
  • Für große Mengen, die sich über einen Schlüsselbereich eingrenzen lassen, ist IDBObjectStore.delete(IDBKeyRange) effizienter als Löschen per Cursor.
  • Kompatibilität: Die Methode wird in allen modernen Browsern und in Web Workern unterstützt. In privaten Fenstern kann IndexedDB je nach Browser eingeschränkt sein.