Start · Sprachen · JavaScript · Referenz · new ExtendableEvent()

new ExtendableEvent()

Methode

Der Konstruktor <code>ExtendableEvent()</code> erzeugt ein neues <code>ExtendableEvent</code>-Objekt. Über dessen <code>waitUntil()</code> lässt sich die Lebensdauer eines Service Workers verlängern.

seit JavaScript Baseline: alle modernen Browser (nur in Service-Wo Kategorie: webapi

Signatur

new ExtendableEvent(type, options)

Beschreibung

Der Konstruktor new ExtendableEvent() erzeugt ein Ereignisobjekt vom Typ ExtendableEvent. Diese Schnittstelle erweitert Event um die Methode waitUntil(). Damit teilt ein Handler dem Browser mit, dass noch asynchrone Arbeit läuft und der Service Worker nicht beendet werden darf, bevor das übergebene Promise erfüllt ist.

Normalerweise erzeugt der Browser solche Ereignisse selbst, etwa install und activate. Abgeleitete Typen wie FetchEvent, PushEvent, NotificationEvent oder SyncEvent baut ebenfalls der Browser. Den Konstruktor ruft man selbst vor allem in drei Fällen auf:

  • Tests: Man löst Lebenszyklus-Handler gezielt aus, um sie zu testen.
  • Eigene Ereignisse: Man verschickt eigene Ereignisse innerhalb des Worker-Kontexts mit dispatchEvent().
  • Unterklassen: Man baut eigene Klassen mit class … extends ExtendableEvent.

Wichtig: Ein von Hand erzeugtes und verschicktes Ereignis verlängert die Lebensdauer des Service Workers nicht. Das tun nur Ereignisse, die der Browser auslöst. Außerdem darf waitUntil() nur aufgerufen werden, solange das Ereignis gerade verarbeitet wird. Das ist die synchrone Phase des Handlers oder die Zeit, in der noch frühere waitUntil-Promises offen sind. Später wirft der Aufruf einen InvalidStateError.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Name des Ereignisses, z. B. "install", "activate" oder ein eigener Name wie "cache-refresh". Groß- und Kleinschreibung wird unterschieden.
$options object {} Optionales Objekt mit den Feldern von EventInit: bubbles (boolean, Standard false), cancelable (boolean, Standard false) und composed (boolean, Standard false). ExtendableEventInit fügt derzeit keine eigenen Felder hinzu.

Rückgabewert

Typ
ExtendableEvent
Beschreibung
Ein neues ExtendableEvent-Objekt mit dem angegebenen Typ und den Optionen, bereit für dispatchEvent().

Beispiele

Ereignis erzeugen und Eigenschaften prüfen

// Im Service-Worker-Kontext (sw.js)
const event = new ExtendableEvent('cache-refresh', { cancelable: true });

console.log(event instanceof ExtendableEvent);
console.log(event instanceof Event);
console.log(event.type, event.cancelable);
console.log(typeof event.waitUntil);
true true cache-refresh true function

Eigenes Ereignis mit waitUntil im Worker verschicken

// sw.js
self.addEventListener('cache-refresh', (event) => {
  event.waitUntil(
    (async () => {
      const cache = await caches.open('app-v2');
      await cache.addAll(['/index.html', '/app.js']);
      console.log('Cache aktualisiert');
    })()
  );
});

self.addEventListener('message', (msg) => {
  if (msg.data === 'refresh') {
    self.dispatchEvent(new ExtendableEvent('cache-refresh'));
    // Die Lebensdauer des Workers sichert hier das message-Ereignis
    // des Browsers ab, nicht das selbst erzeugte Ereignis:
    msg.waitUntil(caches.open('app-v2'));
  }
});
Cache aktualisiert

Install-Handler im Unit-Test auslösen

// Test-Code im Service-Worker-Kontext (z. B. mit einer Test-Bibliothek)
const pending = [];

const fakeInstall = new ExtendableEvent('install');
// waitUntil abfangen, um auf die Promises zu warten
fakeInstall.waitUntil = (p) => pending.push(p);

self.dispatchEvent(fakeInstall);
await Promise.all(pending);

const cache = await caches.open('app-v1');
const keys = await cache.keys();
console.log(`Gecachte Einträge: ${keys.length}`);
Gecachte Einträge: 3

Eigene Unterklasse mit Zusatzdaten

class RefreshEvent extends ExtendableEvent {
  constructor(urls, init = {}) {
    super('refresh', init);
    this.urls = urls;
  }
}

self.addEventListener('refresh', (event) => {
  console.log('Zu laden:', event.urls.join(', '));
  event.waitUntil(caches.open('app').then((c) => c.addAll(event.urls)));
});

self.dispatchEvent(new RefreshEvent(['/a.css', '/b.js']));
Zu laden: /a.css, /b.js

// Wichtig · Fallstricke

  • Nur im Service Worker verfügbar: ExtendableEvent gibt es nur im ServiceWorkerGlobalScope. Im Hauptfenster oder in einem normalen Web Worker ist der Name undefined, der Aufruf wirft dort also einen ReferenceError.
  • Keine Verlängerung der Lebensdauer: Von Hand verschickte Ereignisse halten den Worker nicht am Leben. Deren waitUntil() hat nur im eigenen Code eine Wirkung. Die Lebensdauer sichert man über ein echtes Browser-Ereignis ab, etwa message, fetch oder push.
  • InvalidStateError: Wer waitUntil() außerhalb der Verarbeitung aufruft, bekommt diesen Fehler. Das betrifft einen Aufruf vor dispatchEvent() und einen Aufruf nach dem Ende des Handlers, wenn alle Promises schon erfüllt sind. waitUntil() also immer synchron im Handler aufrufen, nicht erst nach einem await.
  • Abgelehnte Promises: Wird ein an waitUntil() übergebenes Promise bei install abgelehnt, schlägt die Installation fehl. Der Worker wird dann verworfen.
  • Nur HTTPS: Service Worker laufen nur in einem sicheren Kontext, also HTTPS oder localhost.