10

I've written a service worker with help from a tutorial:

var CACHE = 'cache-and-update'; self.addEventListener('install', function (evt) { console.log('The service worker is being installed.'); evt.waitUntil(precache()); }); self.addEventListener('fetch', function (evt) { evt.respondWith(fromCache(evt.request)); evt.waitUntil(update(evt.request)); }); function precache() { return caches.open(CACHE).then(function (cache) { return cache.addAll([ // Nothing. ]); }); } function fromCache(request) { return caches.open(CACHE).then(function (cache) { return cache.match(request).then(function (matching) { return matching || Promise.reject('no-match'); }); }); } function update(request) { return caches.open(CACHE).then(function (cache) { return fetch(request).then(function (response) { return cache.put(request, response); }); }); } 

It always serves from the cache first, then fetches all files, and updates on page reload.

The service worker is registered like this in every HTML file on my server:

<script> navigator.serviceWorker.register('https://www.example.com/sw.js', { scope: '../' }); </script> 

Now the problem is, when I go to a page that isn't cached yet, it first shows me the default Chrome ERR_FAILED error (and the 'no-match' promise rejection).

The sw then fetches it anyway, while showing the error page to the client, and on a reload it works again (because it's served from the cache).

Why is this happening and how can I make the service worker load the page from the server when there's no cached version available?

1 Answer 1

5

You got the fetch listener wrong here, You are rejecting the promise if the file was not found in the cache, you should fetch it then cache it instead of returning Promise.reject('no-match') and you do not need the evt.waitUntil in this case

here is a full snippet to a working service worker. If a request doesn't match anything in the cache, we get it from the network, send it to the page and add it to the cache at the same time.

let cacheName = 'cache-v1'; self.addEventListener('install', (e) => { let cache = caches.open(cacheName).then((c) => { c.addAll([ // nothing ]); }); e.waitUntil(cache); }); self.addEventListener('fetch', function (event) { event.respondWith( caches.open(cacheName).then(function (cache) { return cache.match(event.request).then(function (response) { return response || fetch(event.request).then(function (response) { cache.put(event.request, response.clone()); return response; }); }); }) ); }); 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.