ExtendableEvents – expandable in the dimension “time”

by | 13.06.2020

Progressive Web Apps (PWA) are web applications that use modern browser features. So PWAs can work offline, for example. Many features of a PWA are enabled by so-called ServiceWorkers. Basically, a ServiceWorker is a JavaScript file that is executed in the background by the browser. A ServiceWorker can still be active in the background even if the actual website to which it belongs is no longer open in the browser. However, this article will not deal with ServiceWorkers in general, because there would be far too much to write about. Instead, it will deal with a special event that you will encounter sooner or later when working with ServiceWorkers: the ExtendableEvent.

What are ExtendableEvents?

“Extendable” from “ExtendableEvent” must not be understood as extendable in the sense of object-oriented programming, because the name has a different origin. ExtendableEvents are extensible with regard to the dimension “time”. The duration of an ExtendableEvent can be extended. This is done with the function “waitUntil()”. The function receives a Promise as parameter. As long as the Promise is still outstanding, the ExtendableEvent is not continued or completed.1

An example of ExtentableEvents

A small example will serve as an illustration. To be able to reproduce it, JavaScript knowledge, HTML knowledge, a current browser with ServiceWorker support (Chrome 40+, Mozilla 44)2 and a Node.js installation are required.

While a browser registers a ServiceWorker, i.e. sets it up, the two ExtendableEvents “install” and “activate” are usually triggered. The “activate” event follows directly after the “install” event if no ServiceWorker was registered before. In practice, the “install” event is used, for example, to cache assets such as HTML, JavaScript and CSS files for offline scenarios of a PWA. The subsequent “activate” event can be used to remove obsolete assets of a previous ServiceWorker version from the cache. The removal should only take place in this event, since during the “install” event an older ServiceWorker may still be active and still need the assets. No previous ServiceWorker is active during the “activate” event.3

In the example you shall see that the events “install” and “activate” are triggered one after the other, if it is the registration of the very first ServiceWorker. Afterwards you will extend the duration of the “install” event to three seconds. Give it a try. Create two files in a new folder:

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

Fill the index.html file with this content:

<!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>

and the service-worker.js file with these lines:

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

self.addEventListener('activate', function (event) {
    console.log(`'activate' ausgelöst (${Date()})`);
});
The index.html file consists of an ordinary HTML5 framework. The ServiceWorker is registered in the script tag. In addition, the logic is implemented so that you can remove the ServiceWorker from your browser by clicking on the button “Delete ServiceWorker”.4

If your browser does not yet support ServiceWorkers, you will receive a message.

The ServiceWorker (service-worker.js) displays the time of the two events (“install” and “activate”) in the browser on the developer console. As usual for events, you can register an EventHandler with addEventListener() on ExtendableEvents.

To be able to see the behavior in the browser, you need a server that delivers the two files via the localhost. Follow these steps to do this:

  • Open a normal console in the folder where you have placed the two files.
  • Install “node-static” globally via npm:

 

npm install -g node-static 
  • Run node-static in the console:
static
  • In the browser, open the address “localhost:8080”, where node-static delivers files by default.

In the browser, open the developer console at the address given (F12 → “Console”). There you will see the two log outputs of the “install” and “activate” events with time specifications. The “activate” event should only have been output shortly after the “install” event.

extendable-events-immediate - Blog - t2informatik

To illustrate the ExtendableEvents, the “install” event should now be extended by three seconds. To do this, add five lines in the “install” event handler after the console output in the ServiceWorker so that the service-worker.js file looks like this:

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()})`);
});

The “install” event will now be extended by three seconds using the Promise, which is fulfilled after three seconds. Compared to before, the “active” event is triggered three seconds later. You can also see it in the developer console of your browser. To do this, delete the ServiceWorker using the button, reload the page (“F5”) and read the log output.

extendable-events-wait-until - Blog - t2informatik

Conclusion

You have learned what ExtendableEvents are and how they can be extended with a Promise using the waitUntil() function. In the example you have extended the “install” event of a ServiceWorker with a timeout. In a real web application you would load and cache assets for your PWA during the “install” event so that the PWA can be used offline later.3

 

Notes:

[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

Hendrik Schramm

Hendrik Schramm works at t2informatik as a junior developer. He previously studied computer science at the Berlin School of Economics and Law. About some of his experiences he writes in the t2informatik blog.