Eduardo Bouças
Eduardo Bouças

Reputation: 33

ServiceWorker: when are the files actually cached?

I'm using a ServiceWorker to cache some assets and I want to let the user know once all the files have been successfully cached, so they're aware the content is accessible offline. When is the right moment to do this?

I have several console.log() to have an idea of the flow of things. Here's the moment where I register my ServiceWorker:

if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/serviceWorker.js')
        .then(function(registration) {
            console.log('* ServiceWorker registration successful');
        })
        .catch(function(err) {
            console.log('* ServiceWorker registration failed: ', err);
        });
}

And inside the ServiceWorker:

self.addEventListener('install', function(event) {
    console.log('* Installing Service Worker...');

    event.waitUntil(
        caches.open(cacheName).then(function(cache) {
            console.log('* Opened cache');
            return cache.addAll(filesToCache).then(function () {
                console.log('* Files have been cached!');
            });
        })
    );
});

And the console shows:

* Installing Service Worker...
* Opened cache
* ServiceWorker registration successful
* Files have been cached!

So am I right in thinking that the correct moment to trigger this notification is after .addAll(), so where it currently spits "Files have been cached!"? It would be convenient to do it on register(), but there seems to be a delay between the third and last log messages. If that's, because we're inside the ServiceWorker, would a postMessage() to the client be the best way to send this information across?

Thanks!

Upvotes: 0

Views: 816

Answers (2)

JaffaTheCake
JaffaTheCake

Reputation: 14917

When you register for a SW you'll get a registration once the SW parses and starts installing. You can track its progress using the statechange event:

navigator.serviceWorker.register('/sw.js').then(function(reg) {
  if (!reg.installing) return;
  console.log("There is a ServiceWorker installing");

  var worker = reg.installing;
  worker.addEventListener('statechange', function() {
    if (worker.state == 'redundant') {
      console.log('Install failed');
    }
    if (worker.state == 'installed') {
      console.log('Install successful!');
    }
  });
});

This lets you track install no matter what you're doing in the install step. If you want more fine-grained notifications, you can use postMessage.

Upvotes: 5

Michael Aaron Safyan
Michael Aaron Safyan

Reputation: 95639

The "register()" function completes when the service worker has been both downloaded and installed, so if your install process aborts if the files have not been cached, then you could do that notification after "register()" completed successfully. However, doing the notification after "addAll()" probably makes the most sense (especially if you were to ever reorder your code to perform the caching after ServiceWorker installation rather than during the installation process). The "addAll()" function takes some time to complete because it writes the cached content to disk asynchronously.

Upvotes: 0

Related Questions