2

I'm trying to use a service worker to do the following tasks:

  • Cache a set of pages.
  • Return a page from the cache if requested - if the page is not in the cache return from the server.
  • If there is no response from either the cache or the server return a custom offline page.

I have the following code:

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

  event.waitUntil(

    caches.open('v1').then(function(cache) {
      console.log('Service Worker: Caching Files');
      return cache.addAll([
        '/assets/logo.svg',
        '/assets/app.css',
        '/assets/app.js',
        '/assets/common.js',
        '/offline.html'
      ]);
    })
  );
});

this.addEventListener('fetch', function(event) {
  if (event.request.method != "GET" || event.request.mode == "cors" || event.request.url.startsWith('chrome-extension')) return;
  console.log('Event to be passed', event);

  event.respondWith(
    caches.open('v1').then(function(cache) {
      return cache.match(event.request).then(function(response) {
        if (response) {
          console.log('Service Worker: Returning Cached Response', response);
          return response;
        } else {
          fetch(event.request).then(function(response) {
            console.log('Service Worker: Returning Response from Server', response);
            cache.put(event.request, response.clone());
            return response;
          }).catch((error) => {
            console.log('Fetch failed; returning offline page instead.', error);
            return caches.match('/offline.html');
          });
        }
      });
    })
  );
});

this.addEventListener('activate', function activator(event) {
  console.log('Service Worker: Activating', event);
  event.waitUntil(
    caches.keys().then(function(keys) {
      return Promise.all(keys
        .filter(function(key) {
            return key.indexOf('v1') !== 0;
        })
        .map(function(key) {
            return caches.delete(key);
        })
      );
    })
  );
});

The issue I have is that even when offline I get a 200 response for my request, even though I'm offline and not actually retrieving the file.

I understand this is one of the pre-requisites for a PWA to always return a 200 response, but how can I return an offline page if my response always returns as 200.

Any help, advice or resources on service workers would be useful.

Cheers.

tomhughes
  • 4,597
  • 2
  • 24
  • 33
  • To clarify; You're receiving this `console.log('Service Worker: Returning Response from Server', response);` response when offline and your cache is empty? – Kyle Richardson Jul 22 '17 at 19:49
  • Yeah that's the case. However I'm also getting another error which could be causing it: My console says: "The FetchEvent for "http://localhost:8080/page" resulted in a network error response: an object that was not a Response was passed to respondWith()." – tomhughes Jul 22 '17 at 21:10
  • Based from this related [thread](https://stackoverflow.com/questions/33045517/use-serviceworker-cache-only-when-offline), maybe you're not resolving `respondWith()` correctly in the case where there is no cache match. From this [documentation](https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent/respondWith), the code passed to `respondWith()` is supposed to "resolve by returning a Response or network error to Fetch." *Since you're getting the respondWith warning, it means the caches.match() isn't finding that resource.* – abielita Jul 23 '17 at 13:45

1 Answers1

1

you must handle all events, you can't just "return" if nothing special should happen.

this.addEventListener('fetch', function(event) {
    if (event.request.method != "GET" || event.request.mode == "cors" || event.request.url.startsWith('chrome-extension')){
        event.respondWith(fetch(event.request));
        return;
    }
....

then you must also return your fetch event, otherwise you break the promise chain.

} else {
    return fetch(event.request).then(function(response) {
Stef Chäser
  • 1,911
  • 18
  • 26
  • This seems to be the case, I've got a working solution by returning from the cache in my else statement. Thanks for your help. – tomhughes Jul 26 '17 at 10:42