ExtendableEvents – erweiterbar in der Dimension „Zeit“

von | 13.06.2020

Progressive Web Apps (PWA) sind Web-Anwendungen, die moderne Browserfeatures nutzen. So können PWAs bspw. offline funktionieren. Viele Eigenschaften einer PWA werden durch sogenannte ServiceWorker ermöglicht. Im Grunde handelt es sich bei einem ServiceWorker um eine JavaScript-Datei, die im Hintergrund vom Browser ausgeführt wird. Ein ServiceWorker kann auch dann noch im Hintergrund aktiv sein, wenn die eigentliche Website, zu der er gehört, gar nicht mehr im Browser geöffnet ist. In diesem Artikel soll es jedoch nicht um ServiceWorker im Allgemeinen gehen, denn dazu gäbe es viel zu viel zu schreiben. Es soll stattdessen um ein besonderes Event gehen, das einem bei der Arbeit mit ServiceWorkern früher oder später begegnen wird: das ExtendableEvent.

Was sind ExtendableEvents?

„Extendable“ aus „ExtendableEvent“ darf nicht als erweiterbar im Sinne der Objektorientierten Programmierung verstanden werden, denn der Name hat einen anderen Ursprung. ExtendableEvents sind nämlich hinsichtlich der Dimension „Zeit“ erweiterbar. Die Dauer eines ExtendableEvents lässt sich verlängern (also erweitern). Das geschieht mit der Funktion „waitUntil()“. Als Parameter erhält die Funktion ein Promise. Solange wie das Promise noch ausstehend ist, wird das ExtendableEvent nicht fortgesetzt bzw. abgeschlossen.1

Ein Beispiel für ExtentableEvents

Zur Veranschaulichung soll ein kleines Beispiel dienen. Um es nachvollziehen zu können, benötigen JavaScript-Kenntnisse, HTML-Kenntnisse, einen aktuellen Browser mit ServiceWorker-Unterstützung (ab Chrome 40+, Mozilla 44)2 sowie eine Node.js-Installation

Während ein Browser einen ServiceWorker registriert, d.h. einrichtet, werden in der Regel die zwei ExtendableEvents „install“ und „activate“ ausgelöst. Das „activate“-Event folgt direkt auf das „install“-Event, sofern bisher kein ServiceWorker registriert war. In der Praxis wird das „install“-Event bspw. genutzt, um Assets wie HTML-, JavaScript und CSS-Dateien für Offline-Szenarien einer PWA zu cachen. Das nachfolgende „activate“-Event kann genutzt werden, um veraltete Assets einer vorigen ServiceWorker-Version aus dem Cache zu entfernen. Das Entfernen sollte erst in diesem Event passieren, da während des „install“-Events noch ein älterer ServiceWorker aktiv sein kann, der die Assets noch benötigt. Während des „activate“-Events ist kein voriger ServiceWorker mehr aktiv.3

Im Beispiel sollen Sie sehen, dass die Events „install“ und „activate“ nacheinander ausgelöst werden, sofern es sich um die Registrierung des allerersten ServiceWorkers handelt. Danach werden Sie die Dauer des „install“-Events auf drei Sekunden ausweiten. Probieren Sie es aus. Legen Sie dazu zwei Dateien in einem neuen Ordner an:

  1. index.html
  2. service-worker.js

Füllen Sie die index.html-Datei mit diesem Inhalt:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, initial-scale=1.0">
    <title>ExtendableEvents</title>
</head>

<body>

    <button onclick="unregister(serviceWorkerRegistration)">
        ServiceWorker löschen
    </button>

    <script>
        let serviceWorkerRegistration;

        if ('serviceWorker' in navigator) {
            navigator.serviceWorker.register('./service-worker.js')
                .then((registration) =>
                    serviceWorkerRegistration = registration
                );
        } else {
            alert('Ihr Browser unterstützt keine Service Worker.');
        }

        let unregister = (registration) => {
            registration.unregister()
                .then(() => console.log('ServiceWorker gelöscht'))
                .catch(() => console.log('Löschen des ServiceWorkers fehlgeschlagen'));
        };
    </script>
</body>

</html>

und die service-worker.js-Datei mit diesen Zeilen:

self.addEventListener('install', (event) => {
    console.log(`'install' ausgelöst (${Date()})`);
});

self.addEventListener('activate', function (event) {
    console.log(`'activate' ausgelöst (${Date()})`);
});
Die index.html-Datei besteht aus einem gewöhnlichem HTML5-Grundgerüst. In dem Script-Tag wird der ServiceWorker registriert. Außerdem wird die Logik implementiert, damit Sie den ServiceWorker mit Klick auf den Button „ServiceWorker löschen“ aus Ihrem Browser entfernen können.4 Falls Ihr Browser noch keine ServiceWorker unterstützen sollte, erhalten Sie eine Meldung.

Der ServiceWorker (service-worker.js) gibt den Zeitpunkt der beiden Events („install“ und „activate“) im Browser auf der Entwickler-Konsole aus. Wie bei Events üblich kann man einen EventHandler mit addEventListener() auf ExtendableEvents registrieren.

Damit Sie sich das Verhalten im Browser anschauen können, brauchen Sie einen Server, der die beiden Dateien über den Localhost ausliefert. Befolgen Sie dazu diese Schritte:

  • Öffnen Sie eine normale Konsole in dem Ordner, in dem Sie die beiden Dateien abgelegt haben.
  • Installieren Sie „node-static“ global via npm:

 

npm install -g node-static 
  • Führen Sie node-static in der Konsole aus:
static
  • Öffnen Sie im Browser die Adresse „localhost:8080“, über die node-static standardmäßig Dateien ausliefert.

Öffnen Sie im Browser unter der angegebenen Adresse die Entwickler-Konsole (F12 → „Console“). Dort sehen Sie die beiden Log-Ausgaben der „install“- und „activate“-Events mit Zeitangaben. Das „activate“-Event sollte nur kurz nach dem „install“-Event ausgegeben worden sein.

extendable-events-immediate - Blog - t2informatik

Zur Veranschaulichung der ExtendableEvents soll das „install“-Event nun um drei Sekunden verlängert werden. Fügen Sie im ServiceWorker dazu fünf Zeilen im „install“-EventHandler nach der Konsolenausgabe ein, sodass die service-worker.js-Datei so aussieht:

self.addEventListener('install', (event) => {
    console.log(`'install' ausgelöst (${Date()})`);

    let waitTime = 3000;
    let promise = new Promise((resolve) =>
        setTimeout(resolve, waitTime)
    );
    event.waitUntil(promise);
});

self.addEventListener('activate', function (event) {
    console.log(`'activate' ausgelöst (${Date()})`);
});

Das „install“-Event wird jetzt mithilfe des Promises, das sich nach drei Sekunden erfüllt, um drei Sekunden verlängert. Im Vergleich zu vorher wird das „active“-Event drei Sekunden später ausgelöst. Auch in der Entwickler-Konsole Ihres Browsers sehen Sie es. Löschen Sie dazu den ServiceWorker mithilfe des Buttons, laden die Seite neu („F5“) und lesen die Log-Ausgaben.

extendable-events-wait-until - Blog - t2informatik

Fazit

Sie haben gelernt, was ExtendableEvents sind und wie diese mit einem Promise über die waitUntil()-Funktion verlängert werden können. Im Beispiel haben Sie das „install“-Event eines ServiceWorkers mit einem Timeout verlängert. In einer richtigen Web-Anwendung würden Sie während des „install“-Events Assets für Ihre PWA laden und cachen, damit die PWA später offline genutzt werden kann.3

 

Hinweise:

Interessieren Sie sich für weitere Tipps aus der Praxis? Testen Sie unseren wöchentlichen Newsletter mit interessanten Beiträgen, Downloads, Empfehlungen und aktuellem Wissen.

[1] https://developer.mozilla.org/de/docs/Web/API/ExtendableEvent
[2] https://jakearchibald.github.io/isserviceworkerready/index.html
[3] https://developer.mozilla.org/de/docs/Web/API/Service_Worker_API/Using_Service_Workers
[4] https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration/unregister

Hendrik Schramm hat im t2informatik Blog weitere Beiträge veröffentlicht:

t2informatik Blog: Die Telemetrie bei VS Code deaktivieren

Die Telemetrie bei VS Code deaktivieren

t2informatik Blog: Webanwendung im lokalen Netzwerk zugänglich machen

Webanwendung im lokalen Netzwerk zugänglich machen

Hendrik Schramm
Hendrik Schramm

Hendrik Schramm ist bei t2informatik als Softwareentwickler tätig. Zuvor hat er Informatik an der Hochschule für Wirtschaft und Recht in Berlin studiert. Über einige seiner Erfahrungen schreibt er hier im t2informatik Blog.