8

I have the following service worker code in my Vue app:

main.js

if (navigator.serviceWorker) {
  navigator.serviceWorker.register('/service-worker.js').catch(function() {
    console.log('Service worker registration failed.');
  });
}

service-worker.js

let currCacheName = 'premium-poker-tools-5';

self.addEventListener('install', function(event) {
  event.waitUntil(
    caches.open(currCacheName).then(function(cache) {
      let promise = cache.addAll([
        '/',
        'app.js',
        'c7d016677eb7e912bc40.worker.js',
        'f328c7e2b379df12fa4c.worker.js',
        'static/logo.png',
        'static/favicon.png',
        'static/loading.svg',
        'static/cards/ace-of-clubs.png',
        'static/cards/king-of-clubs.png',
        'static/cards/queen-of-clubs.png',
        'static/cards/jack-of-clubs.png',
        'static/cards/ten-of-clubs.png',
        'static/cards/nine-of-clubs.png',
        'static/cards/eight-of-clubs.png',
        'static/cards/seven-of-clubs.png',
        'static/cards/six-of-clubs.png',
        'static/cards/five-of-clubs.png',
        'static/cards/four-of-clubs.png',
        'static/cards/three-of-clubs.png',
        'static/cards/two-of-clubs.png',
        'static/cards/ace-of-spades.png',
        'static/cards/king-of-spades.png',
        'static/cards/queen-of-spades.png',
        'static/cards/jack-of-spades.png',
        'static/cards/ten-of-spades.png',
        'static/cards/nine-of-spades.png',
        'static/cards/eight-of-spades.png',
        'static/cards/seven-of-spades.png',
        'static/cards/six-of-spades.png',
        'static/cards/five-of-spades.png',
        'static/cards/four-of-spades.png',
        'static/cards/three-of-spades.png',
        'static/cards/two-of-spades.png',
        'static/cards/ace-of-hearts.png',
        'static/cards/king-of-hearts.png',
        'static/cards/queen-of-hearts.png',
        'static/cards/jack-of-hearts.png',
        'static/cards/ten-of-hearts.png',
        'static/cards/nine-of-hearts.png',
        'static/cards/eight-of-hearts.png',
        'static/cards/seven-of-hearts.png',
        'static/cards/six-of-hearts.png',
        'static/cards/five-of-hearts.png',
        'static/cards/four-of-hearts.png',
        'static/cards/three-of-hearts.png',
        'static/cards/two-of-hearts.png',
        'static/cards/ace-of-diamonds.png',
        'static/cards/king-of-diamonds.png',
        'static/cards/queen-of-diamonds.png',
        'static/cards/jack-of-diamonds.png',
        'static/cards/ten-of-diamonds.png',
        'static/cards/nine-of-diamonds.png',
        'static/cards/eight-of-diamonds.png',
        'static/cards/seven-of-diamonds.png',
        'static/cards/six-of-diamonds.png',
        'static/cards/five-of-diamonds.png',
        'static/cards/four-of-diamonds.png',
        'static/cards/three-of-diamonds.png',
        'static/cards/two-of-diamonds.png',
        'static/feedback/1.png',
        'static/feedback/2.png',
        'static/feedback/3.png',
        'static/feedback/4.png',
        'static/feedback/flop-selector.png',
        'static/feedback/green-grid-squares.png',
        'static/feedback/user-set-range-to-simulate-to-street.png',
        'static/guides/beginners-guide/1.png',
        'static/guides/beginners-guide/2.png',
        'static/guides/beginners-guide/3.png',
        'static/guides/beginners-guide/4.png',
        'static/guides/beginners-guide/5.png',
        'static/guides/beginners-guide/6.png',
        'static/guides/beginners-guide/7.png',
        'static/guides/beginners-guide/8.png',
        'static/guides/beginners-guide/9.png',
        'static/guides/beginners-guide/10.png',
        'static/guides/beginners-guide/11.png',
        'static/guides/beginners-guide/12.png',
        'static/guides/beginners-guide/13.png',
        'static/guides/beginners-guide/14.png',
        'static/guides/beginners-guide/15.png',
        'static/guides/beginners-guide/16.png',
        'static/guides/beginners-guide/17.png',
        'static/guides/beginners-guide/18.png',
        'static/guides/beginners-guide/19.png',
        'static/guides/beginners-guide/20.png',
        'static/guides/beginners-guide/21.png',
        'static/guides/faq/double-counting/1.png',
        'static/guides/faq/hit-percentage-calculation/1.png',
        'static/guides/faq/hit-percentage-calculation/2.png',
        'static/guides/faq/hit-percentage-calculation/3.png',
        'static/guides/faq/insights/1.png',
        'static/guides/faq/insights/2.png',
        'static/guides/faq/insights/3.png',
        'static/guides/faq/insights/4.png',
        'static/guides/faq/insights/5.png',
        'static/guides/faq/insights/6.png',
        'static/guides/faq/insights/7.png',
        'static/guides/faq/insights/8.png',
        'static/guides/faq/set-checks-to-default/1.png',
        'static/guides/quick-guide/1.png',
        'static/guides/quick-guide/2.png',
        'static/guides/quick-guide/3.png',
        'static/guides/quick-guide/4.png',
        'static/guides/quick-guide/5.png',
        'static/guides/quick-guide/6.png',
        'static/guides/quick-guide/7.png',
        'static/guides/quick-guide/8.png',
        'static/guides/quick-guide/save-load-scenario.png',
        'static/home/1.png',
        'static/home/2.png',
        'static/home/3.png',
        'static/settings/equity-calculator-insights-not-visible.png',
        'static/settings/equity-calculator-insights-visible.png',
        'static/settings/outcome-analyzer-checkboxes-collapsed-1.png',
        'static/settings/outcome-analyzer-checkboxes-collapsed-2.png',
        'static/settings/outcome-analyzer-checkboxes-included-1.png',
        'static/settings/outcome-analyzer-checkboxes-included-2.png',
        'static/settings/outcome-analyzer-hands.png',
        'static/settings/outcome-analyzer-insights-not-visible.png',
        'static/settings/outcome-analyzer-insights-visible.png',
        'static/settings/saved-ranges-1.png',
        'static/settings/saved-ranges-2.png',
        'static/settings/saved-ranges-3.png',
        'static/settings/saved-ranges-4.png',
        'static/settings/included-selectors/double-slider-selector.png',
        'static/settings/included-selectors/log-double-slider-selector.png',
        'static/settings/included-selectors/saved-ranges-selector.png',
        'static/settings/included-selectors/single-slider-selector.png',
        'static/settings/included-selectors/tier-and-category-selector.png',
        'static/settings/tiers/tiers.png',
        'static/settings/visual/dont-show-num-combos-in-range.png',
        'static/settings/visual/green-grid-squares.png',
        'static/settings/visual/multicolored-grid-squares.png',
        'static/settings/visual/show-num-combos-in-range.png',
      ]).then(function () {
        console.log('Successfully cached everything.')
      }).catch(function (error) {
        console.log('Problem caching: ', error);
      });

      return promise;
    }).catch(function () {
      console.error('Error with caches.open or cache.addAll');
    })
  );
});

self.addEventListener('activate', function(event) {
  event.waitUntil(
    caches.keys()
      .then(function getOldCachesThatBeginWithPremiumPokerToolsDash (cacheNames) {
        return cacheNames.filter(function (cacheName) {
          return cacheName.startsWith('premium-poker-tools-') && (cacheName !== currCacheName);
        });
      })
      .then(function removeOldCachesThatBeginWithPremiumPokerToolsDash (oldCachesThatBeginWithPremiumPokerToolsDash) {
        let removeCachePromises = [];

        oldCachesThatBeginWithPremiumPokerToolsDash.forEach(function (oldCacheThatBeginsWithPremiumPokerToolsDash) {
          removeCachePromises.push(caches.delete(oldCacheThatBeginsWithPremiumPokerToolsDash));
        });

        return Promise.all(removeCachePromises);
      })
  );
});

self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request).then(function (response) {
      if (response) {
        return response;
      }

      return fetch(event.request);
    }).catch(function () {
      console.error('Error trying to match event request to cache.');
    })
  );
});

When I comment out 'c7d016677eb7e912bc40.worker.js' and 'f328c7e2b379df12fa4c.worker.js', it works fine. But when I uncomment them, here's what happens:

  • I start off going to the Dev Tools and unregistering any service workers and deleting anything in Cache Storage so that I start off with a clean slate.
  • I load localhost:8080.
  • The service worker stays in the installing state.
  • In Cache Storage, I see that c7d016677eb7e912bc40.worker.js and f328c7e2b379df12fa4c.worker.js have been successfully cached.
  • However, "Successfully cached everything." isn't being logged to the console. But "Problem caching: " isn't being logged either.

I understand that the promise you pass to event.waitUntil() lets the browser know when your install completes, and if it was successful. So clearly there is some issue going on with the promise. But I don't know what the issue is. It's not hitting the .then block or the .catch block, and when I look at Cache Storage in the Dev Tools, it appears that 'c7d016677eb7e912bc40.worker.js' and 'f328c7e2b379df12fa4c.worker.js' are being successfully cached.

Edit: I am using worker-loader. I get the feeling that the issue is related to how the worker files are loaded, but I don't see why there would be a problem, because when I go to localhost:8080/c7d016677eb7e912bc40.worker.js or localhost:8080/f328c7e2b379df12fa4c.worker.js, I get back the JS file.

Also, I have made sure that prefixes in c7d016677eb7e912bc40.worker.js and f328c7e2b379df12fa4c.worker.js are accurate. Eg. that c7d016677eb7e912bc40 and f328c7e2b379df12fa4c are accurate.

Update:

enter image description here

enter image description here

enter image description here

Adam Zerner
  • 17,797
  • 15
  • 90
  • 156
  • What is the service worker's statue reported by chrome? is it `waiting to activated` with an orange icon beside it – Hyyan Abo Fakher Sep 11 '18 at 08:07
  • @HyyanAboFakher The status is `installing`, which comes before the `waiting to be activated` state. I added pictures to demonstrate. – Adam Zerner Sep 11 '18 at 17:33
  • Check the URL /ngsw/state that may some errors in there. – PeterS Sep 18 '18 at 15:06
  • @PeterS I don't see any requests being made to `/ngsw/state` in the network tab. When I visit `/ngsw/state` - eg type it in to the URL bar and press enter - the response to `GET /ngsw/state` is just my `index.html` file. – Adam Zerner Sep 18 '18 at 17:52
  • @PeterS It [seems](https://gist.github.com/alxhub/76aa639d9a37cdca30938f7938d9146c#ngswstate) that `/ngsw/state` is specific to service workers in the context of Angular. I am using Vue. – Adam Zerner Sep 20 '18 at 19:41
  • @AdamZerner yes sorry it is, you may want to add that to your list of tags. – PeterS Sep 25 '18 at 10:18

1 Answers1

0

This doesn't work how you think it does:

caches.open(currCacheName).then(function(cache) {
  let promise = cache.addAll([

You are defining a variable called promise here, but it doesn't replace cache, which is the promise which needs to be fulfilled.

You have a load of assets to cache and then:

 'static/settings/visual/show-num-combos-in-range.png',
      ]).then(function () {
        console.log('Successfully cached everything.')
      }).catch(function (error) {
        console.log('Problem caching: ', error);
      });

You don't return anything here, so .then won't run, but it's not an error, so .catch won't either.

Your cache gets populated, but your promise for extendableEvent.waitUntil() is never settled, so installation never completes.

Either scrap your promise variable / console.logs and return the cache.addAll like this:

self.addEventListener('install', function(event) {
  event.waitUntil(
    caches.open(currCacheName).then(function(cache) {
      return cache.addAll([
        '/',
        'app.js',
        'static/settings/visual/show-num-combos-in-range.png',
      ])
    })
  );
});

Or make your function async, like this:

self.addEventListener('install', event => {
  event.waitUntil(async function() {
    const cache = await caches.open(currCacheName);
    await cache.addAll([
        '/',
        'app.js',
        'static/settings/visual/show-num-combos-in-range.png',
    ]);
  }());
});
miknik
  • 5,748
  • 1
  • 10
  • 26
  • 1) The `return cache.addAll` approach doesn't work; the same thing happens as what I described in the question with the service worker remaining in the `installing` state. – Adam Zerner Sep 20 '18 at 19:34
  • 2) _"You are defining a variable called promise here, but it doesn't replace cache, which is the promise which needs to be fulfilled."_ I thought that `cache` is an object, not a promise, and that what needs to happen is that the `.then` block of `caches.open` needs to return something in order to trigger the `caches.open` promise to resolve (which would trigger `event.waitUntil` to finish). If so, I don't see why it would matter if you assign to the `promise` variable, because either way the `.then` block of `caches.open` is returning something. – Adam Zerner Sep 20 '18 at 19:36
  • 3) Even if assigning to the `promise` variable causes issues with `caches.open`, why would it cause issues with the `.then` and `.catch` blocks of `cache.addAll`? – Adam Zerner Sep 20 '18 at 19:38
  • 4) If there is indeed an issue with the `let promise = cache.addAll` approach, why does it work when I comment out `c7d016677eb7e912bc40.worker.js` and `f328c7e2b379df12fa4c.worker.js`? – Adam Zerner Sep 20 '18 at 19:49