GoogleChromeLabs/sw-toolbox

Failing to activate SW and returning failed fetch promises

pmbanugo opened this issue · 3 comments

I have my SW implemented as shown

importScripts("/resources/sw-toolbox.js");

const version = "0.12";

self.addEventListener("install", function(event){
    event.waitUntil(
        caches.open(version)
        .then(function(cache){
            return cache.addAll(["/index.html",
                        "/",
                        "/history.html",
                        "/manifest.json",
                        "/resources/mdl/material.indigo-pink.min.css",
                        "/resources/mdl/material.min.js",
                        "/resources/mdl/MaterialIcons-Regular.woff2",
                        "/resources/mdl/material-icons.css",
                        "/css/style.css",
                        "/resources/dialog-polyfill/dialog-polyfill.js",
                        "/resources/dialog-polyfill/dialog-polyfill.css",
                        "/js/transpiled/index.js",
                        "/js/transpiled/history.js",
                        "/js/transpiled/shared.js",
                        "/hoodie/client.js"]);
    })
    .then((r) => {
        console.log("SW skipping wait");
        self.skipWaiting();
        console.log("SW Installed");
        return r;
    })
    .catch(console.error));
});

self.addEventListener("activate", function (event){
    console.log("SW claiming");
    self.clients.claim();
    console.log("SW activated");

    event.waitUntil(
        caches.keys()
        .then(function (keys){
            return Promise.all(keys.filter(function (key) {
                return key !== version;
            }).map(function (key) {
                return caches.delete(key);
            }));
        })
        .then((r) => {
            console.log(r);
            return r;
        })
        .catch(console.error));
});



toolbox.router.get("/hoodie/client.js", toolbox.cacheFirst, {
    cache: {
        name: version,
        maxAgeSeconds: 60 * 60 * 24 * 365
    }
});

toolbox.router.get("/hoodie/*", toolbox.networkOnly);

toolbox.router.get("/*", toolbox.cacheFirst, {
    cache: {
        name: version,
        maxAgeSeconds: 60 * 60 * 24 * 365
    }
});

I'm using Hoodie, a JS library which uses PouchDB behind the scene and when I authenticate a user with it, it continuously tries to sync data.

Because I want to use cacheFirst for every call to my domain using toolbox.router.get("/*", toolbox.cacheFirst but then allow calls to hoodie API to pass through the network toolbox.router.get("/hoodie/*", toolbox.networkOnly); , I have implemented my sw as such. But then it seems that when I have a new SW, the call to /hoodie/store/api/... fails and show an error in the dev tools saying the promise rejected. A couple of rejected fetch request get's shown before the SW activates after a succesful install. Sometimes even it take a while to enter the installing event.

If I take off the statement toolbox.router.get("/hoodie/*", toolbox.networkOnly); and then list the files and directories I want to use cache first for, it works as I expect without problem installing and activating.

toolbox.router.get("/hoodie/client.js", toolbox.cacheFirst, {
    cache: {
        name: version,
        maxAgeSeconds: 60 * 60 * 24 * 365
    }
});

//toolbox.router.get("/hoodie/*", toolbox.networkOnly);

// toolbox.router.get("/*", toolbox.cacheFirst, {
//     cache: {
//         name: version,
//         maxAgeSeconds: 60 * 60 * 24 * 365
//     }
// });

toolbox.router.get("/", toolbox.cacheFirst, {
    cache: {
        name: version,
        maxAgeSeconds: 60 * 60 * 24 * 365
    }
});

toolbox.router.get("/index.html", toolbox.cacheFirst, {
    cache: {
        name: version,
        maxAgeSeconds: 60 * 60 * 24 * 365
    }
});

toolbox.router.get("/history.html", toolbox.cacheFirst, {
    cache: {
        name: version,
        maxAgeSeconds: 60 * 60 * 24 * 365
    }
});

toolbox.router.get("/manifest.json", toolbox.cacheFirst, {
    cache: {
        name: version,
        maxAgeSeconds: 60 * 60 * 24 * 365
    }
});

toolbox.router.get("/resources/*", toolbox.cacheFirst, {
    cache: {
        name: version,
        maxAgeSeconds: 60 * 60 * 24 * 365
    }
});

toolbox.router.get("/css/*", toolbox.cacheFirst, {
    cache: {
        name: version,
        maxAgeSeconds: 60 * 60 * 24 * 365
    }
});

toolbox.router.get("/js/*", toolbox.cacheFirst, {
    cache: {
        name: version,
        maxAgeSeconds: 60 * 60 * 24 * 365
    }
});

Screen Shot 2017-02-25 at 01.22.52.png

Is this an issue with using toolbox.networkOnly ? I was reading this

Is there a better way to arrange the registrations?

Am I misunderstanding something or is it sw-toolbox error?

Is this how service worker works?

mbj36 commented
self.addEventListener('install', (event) => {
    console.info('Event: Install');

    event.waitUntil(
      caches.open(cacheName)
      .then((cache) => {
        //[] of files to cache & if any of the file not present `addAll` will fail
        return cache.addAll(files)
        .then(() => {
          console.info('All files are cached');
          return self.skipWaiting(); //To forces the waiting service worker to become the active service worker
        })
        .catch((error) =>  {
          console.error('Failed to cache', error);
        })
      })
    );
  });


  self.addEventListener('fetch', (event) => {
  console.info('Event: Fetch');

  var request = event.request;

  //Tell the browser to wait for newtwork request and respond with below
  event.respondWith(
    //If request is already in cache, return it
    caches.match(request).then((response) => {
      if (response) {
        return response;
      }

      //if request is not cached, add it to cache
      return fetch(request).then((response) => {
        var responseToCache = response.clone();
        caches.open(cacheName).then((cache) => {
            cache.put(request, responseToCache).catch((err) => {
              console.warn(request.url + ': ' + err.message);
            });
          });

        return response;
      });
    })
  );
});

/*
  ACTIVATE EVENT: triggered once after registering, also used to clean up caches.
*/

//Adding `activate` event listener
self.addEventListener('activate', (event) => {
  console.info('Event: Activate');

  //Remove old and unwanted caches
  event.waitUntil(
    caches.keys().then((cacheNames) => {
      return Promise.all(
        cacheNames.map((cache) => {
          if (cache !== cacheName) {     //cacheName = 'cache-v1'
            return caches.delete(cache); //Deleting the cache
          }
        })
      );
    })
  );
});

try this code and i had a variable 'files' where i had the array of all the files that i wanted to cache.basically change the variable accordingly in this code

self.addEventListener('fetch', (event) => {
  console.info('Event: Fetch');

  var request = event.request;

  //Tell the browser to wait for newtwork request and respond with below
  event.respondWith(
    //If request is already in cache, return it
    caches.match(request).then((response) => {
      if (response) {
        return response;
      }

      //if request is not cached, add it to cache
      return fetch(request).then((response) => {
        var responseToCache = response.clone();
        caches.open(cacheName).then((cache) => {
            cache.put(request, responseToCache).catch((err) => {
              console.warn(request.url + ': ' + err.message);
            });
          }); 

        return response;
      });
    })
  );
});

with that it means I'll cache every request, doens't it?

I'm suspecting the toolbox.networkOnly behaves in a way that causes request to fail when service worker is installig

What is the solution to this issue? I have similar issue.