Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ServiceWorker's 'fetch': Object that was not a Response was passed to respondWith()

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

like image 603
filipealmda Avatar asked Sep 12 '19 10:09

filipealmda


People also ask

What is event respondWith?

The respondWith() method of FetchEvent prevents the browser's default fetch handling, and allows you to provide a promise for a Response yourself.

What is a fetch event?

This is the event type for fetch events dispatched on the service worker global scope. It contains information about the fetch, including the request and how the receiver will treat the response. It provides the event. respondWith() method, which allows us to provide a response to this fetch.


1 Answers

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;
})());
like image 187
Jeff Posnick Avatar answered Sep 21 '22 06:09

Jeff Posnick