6
votes

Service worker 'fetch' not returning Response object

I'm trying to answer the request with cached content. If the cache doesn't have the required content, I'm fetching from the server, putting the response in the cache and returning it.

self.addEventListener('fetch', function (event) {
  if (event.request.method != 'GET')
    return;
  event.waitUntil((async () => {
    // some IndexedDB stuff which works fine
  })());
  event.respondWith((async () => { //<----------- this is line 154
    var freshResource = fetch(event.request).then(async function (response) {
      if (!response || response.status !== 200 || response.type !== 'basic') {
        return response;
      }
      if (ENABLE_DYNAMIC_CACHING) {
        var responseToCache = response.clone();
        caches.open(DYNAMIC_CACHE).then(function (cache) {
          cache.put(event.request, responseToCache);
        });
      }
      return response;
    }).catch(function (error) {
      console.err('Error: ' + error.message);
    });
    caches.match(event.request).then(async function (resp) {
      return resp || freshResource;
    }).catch(function (e) {
      return freshResource;
    });
  })());
});

When I request a page, it doesn't load, and I get this:

The FetchEvent for "http://localhost:64228" resulted in a network error response: an object that was not a Response was passed to respondWith(). ... @service-worker.js:154

I wonder if this could have to do with the async stuff...

1

1 Answers

4
votes

Yes, inside of an async function, it's preferable to use await rather than a .then() chain to structure your promise-based logic.

Here's a roughly equivalent rewrite. You might need to reorder some of the logic depending on the exact behavior you're after:

event.respondWith((async () => {
  const cachedResponse = await caches.match(event.request);
  if (cachedResponse) {
    return cachedResponse;
  }

  const response = await fetch(event.request);

  if (!response || response.status !== 200 || response.type !== 'basic') {
    return response;
  }

  if (ENABLE_DYNAMIC_CACHING) {
    const responseToCache = response.clone();
    const cache = await caches.open(DYNAMIC_CACHE)
    await cache.put(event.request, response.clone());
  }

  return response;
})());