Start · Sprachen · JavaScript · Referenz · ServiceWorkerGlobalScope: contentdelete

ServiceWorkerGlobalScope: contentdelete

Ereignis

Wird im Service Worker ausgelöst, wenn der Nutzer über die Oberfläche des Browsers einen Eintrag aus dem Content Index löscht.

seit JavaScript Experimentell: Chrome/Edge 84+ (v. a. Android), ni Kategorie: webapi

Signatur

self.addEventListener("contentdelete", (event: ContentIndexEvent) => { … })

Beschreibung

Das Ereignis contentdelete gehört zur Content Index API und wird im ServiceWorkerGlobalScope ausgelöst, wenn ein zuvor mit registration.index.add() registrierter Offline-Inhalt vom User Agent aus dem Index entfernt wird. Das passiert typischerweise, wenn der Nutzer den Eintrag in der Browser-Oberfläche löscht, etwa in Chrome für Android unter „Downloads“ → „Artikel für dich“ bzw. „Offline-Inhalte“.

Der Handler bekommt ein ContentIndexEvent, dessen Eigenschaft id die ID des gelöschten Eintrags enthält. Damit räumst du die zugehörigen Daten auf, also Einträge in der Cache Storage API, Datensätze in IndexedDB oder Bilder, die nur für diesen Inhalt heruntergeladen wurden. So bleibt der Offline-Speicher deiner App stimmig mit dem, was der Nutzer im Browser sieht.

Du kannst den Handler mit self.addEventListener("contentdelete", …) oder über die Eigenschaft self.oncontentdelete registrieren. Da das Ereignis von ExtendableEvent erbt, solltest du asynchrone Aufräumarbeiten in event.waitUntil() verpacken. Sonst kann der Browser den Service Worker beenden, bevor die Arbeiten fertig sind.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Name des Ereignisses, hier immer "contentdelete".
$listener Pflicht (event: ContentIndexEvent) => void Handler-Funktion. Sie bekommt ein ContentIndexEvent, dessen Eigenschaft event.id (string) den gelöschten Eintrag nennt.
$event.id Pflicht string Nur lesbar. Die ID, die beim Aufruf von registration.index.add({ id, … }) vergeben wurde.
$event.waitUntil(promise) (promise: Promise<any>) => void Geerbt von ExtendableEvent. Hält den Service Worker am Leben, bis das übergebene Promise erfüllt ist.

Rückgabewert

Typ
void
Beschreibung
Der Handler gibt keinen Wert zurück. Wenn du asynchron aufräumst, übergib das Promise an event.waitUntil().

Beispiele

Gecachten Artikel beim Löschen durch den Nutzer entfernen (addEventListener)

// sw.js
self.addEventListener('contentdelete', (event) => {
  console.log('Vom Nutzer gelöscht:', event.id);
  event.waitUntil((async () => {
    const cache = await caches.open('offline-articles');
    // IDs wurden beim Hinzufügen als "article-<slug>" vergeben
    const slug = event.id.replace('article-', '');
    await cache.delete(`/articles/${slug}`);
    await cache.delete(`/images/${slug}.webp`);
  })());
});
Vom Nutzer gelöscht: article-service-worker-grundlagen

Handler über die Eigenschaft oncontentdelete setzen

// sw.js – Alternative zur addEventListener-Variante
self.oncontentdelete = (event) => {
  event.waitUntil(
    caches.open('podcasts').then((cache) => cache.delete(`/episodes/${event.id}.mp3`))
  );
};

// Handler später wieder entfernen
// self.oncontentdelete = null;

Gegenstück auf der Seite: Inhalt in den Index aufnehmen

// main.js – läuft im Fenster, nicht im Service Worker
const saveOffline = async (slug, title) => {
  const registration = await navigator.serviceWorker.ready;
  if (!('index' in registration)) {
    console.warn('Content Index API wird nicht unterstützt');
    return;
  }
  const cache = await caches.open('offline-articles');
  await cache.add(`/articles/${slug}`);
  await registration.index.add({
    id: `article-${slug}`,
    title,
    description: 'Offline gespeicherter Artikel',
    category: 'article',
    url: `/articles/${slug}`,
    icons: [{ src: `/images/${slug}-icon.png`, sizes: '96x96', type: 'image/png' }]
  });
  console.log('Gespeichert:', await registration.index.getAll());
};

saveOffline('service-worker-grundlagen', 'Service Worker – Grundlagen');
Gespeichert: [{ id: "article-service-worker-grundlagen", title: "Service Worker – Grundlagen", … }]

IndexedDB-Eintrag passend zur gelöschten ID entfernen

// sw.js
const openDb = () => new Promise((resolve, reject) => {
  const req = indexedDB.open('offline-db', 1);
  req.onupgradeneeded = () => req.result.createObjectStore('articles', { keyPath: 'id' });
  req.onsuccess = () => resolve(req.result);
  req.onerror = () => reject(req.error);
});

self.addEventListener('contentdelete', (event) => {
  event.waitUntil((async () => {
    const db = await openDb();
    await new Promise((resolve, reject) => {
      const tx = db.transaction('articles', 'readwrite');
      tx.objectStore('articles').delete(event.id);
      tx.oncomplete = resolve;
      tx.onerror = () => reject(tx.error);
    });
  })());
});

// Wichtig · Fallstricke

  • Experimentell: Die Content Index API gibt es nur in Chromium-Browsern (Chrome/Edge 84+). Eine sichtbare Oberfläche dafür bietet praktisch nur Chrome für Android. Firefox und Safari unterstützen sie nicht. Prüfe deshalb vorher mit 'index' in registration, ob die API vorhanden ist.
  • Nur bei Löschung durch den User Agent: Das Ereignis wird nicht ausgelöst, wenn deine eigene Seite registration.index.delete(id) aufruft. In diesem Fall musst du die Caches selbst direkt aufräumen.
  • Das Ereignis gibt es nur im Service-Worker-Kontext und nur in einem sicheren Kontext (HTTPS oder localhost), nicht im window.
  • Verwende event.waitUntil() für asynchrone Aufräumarbeiten. Sonst kann der Service Worker mitten im Löschvorgang beendet werden.
  • Nimm nur Inhalte in den Index auf, die wirklich offline verfügbar sind. Chrome prüft das und kann Einträge verwerfen, deren url offline nicht lädt.