Progressive web app Uncaught (in promise) TypeError: Failed to fetch

Viewed 43995

I started learning PWA (Progressive Web App) and I have problem, console "throws" error Uncaught (in promise) TypeError: Failed to fetch.

Anyone know what could be the cause?

let CACHE = 'cache';

self.addEventListener('install', function(evt) {
    console.log('The service worker is being installed.');
    evt.waitUntil(precache());
});

self.addEventListener('fetch', function(evt) {
    console.log('The service worker is serving the asset.');
    evt.respondWith(fromCache(evt.request));
});
function precache() {
    return caches.open(CACHE).then(function (cache) {
        return cache.addAll([
            '/media/wysiwyg/homepage/desktop.jpg',
            '/media/wysiwyg/homepage/bottom2_desktop.jpg'
        ]);
    });
}
function fromCache(request) {
    return caches.open(CACHE).then(function (cache) {
        return cache.match(request).then(function (matching) {
            return matching || Promise.reject('no-match');
        });
    });
}
6 Answers

I think this is due to the fact that you don't have a fallback strategy. event.respondWith comes with a promise which you have to catch if there's some error.

So, I'd suggest that you change your code from this:

self.addEventListener('fetch', function(evt) {        
    console.log('The service worker is serving the asset.');
    evt.respondWith(fromCache(evt.request));
});                   

To something like this:

addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request)
      .then(function(response) {
        if (response) {
          return response;     // if valid response is found in cache return it
        } else {
          return fetch(event.request)     //fetch from internet
            .then(function(res) {
              return caches.open(CACHE_DYNAMIC_NAME)
                .then(function(cache) {
                  cache.put(event.request.url, res.clone());    //save the response for future
                  return res;   // return the fetched data
                })
            })
            .catch(function(err) {       // fallback mechanism
              return caches.open(CACHE_CONTAINING_ERROR_MESSAGES)
                .then(function(cache) {
                  return cache.match('/offline.html');
                });
            });
        }
      })
  );
});          

NOTE: There are many strategies for caching, what I've shown here is offline first approach. For more info this & this is a must read.

I had the same error and in my case Adblock was blocking the fetch to an url which started by 'ad' (e.g. /adsomething.php)

In my case, the files to be cached were not found (check the network console), something to do with relative paths, since I am using localhost and the site is inside a sub-directory because I develop multiple projects on a XAMPP server.

So I changed

let cache_name = 'Custom_name_cache';

let cached_assets = [
    '/',
    'index.php',
    'css/main.css',
    'js/main.js'
];

self.addEventListener('install', function (e) {
    e.waitUntil(
        caches.open(cache_name).then(function (cache) {
            return cache.addAll(cached_assets);
        })
    );
});

To below: note the "./" on the cached_assets

let cache_name = 'Custom_name_cache';

let cached_assets = [
    './',
    './index.php',
    './css/main.css',
    './js/main.js'
];

self.addEventListener('install', function (e) {
    e.waitUntil(
        caches.open(cache_name).then(function (cache) {
            return cache.addAll(cached_assets);
        })
    );
});

Try to use / before adding or fetching any path like /offline.html or /main.js

Cached files reference should be correct otherwise the fetch will fail. Even if one reference is incorrect the whole fetch will fail.

let cache_name = 'Custom_name_cache';


let cached_files = [
    '/',
    'index.html',
    'css/main.css',
    'js/main.js'
]; 
// The reference here should be correct. 

self.addEventListener('install', function (e) {
    e.waitUntil(
        caches.open(cache_name).then(function (cache) {
            return cache.addAll(cached_files);
        })
    );
});
Related