Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wait for ServiceWorker to complete registering before subscribing

I am using a ServiceWorker to implement user notifications. When the user first visits the site and approves the notification, the ServiceWorker is registered and subscribed to:

if ('serviceWorker' in navigator) {
 console.log('Service Worker is supported');
 navigator.serviceWorker.register('/js/sw.js').then(function(reg) {
   if(/chrom(e|ium)/.test(navigator.userAgent.toLowerCase())){
       reg.pushManager.subscribe({
           userVisibleOnly: true
       }).then(function(sub) {
           console.log('endpoint:', sub.endpoint);
           endpoint = sub.endpoint;
           fetch(MY_API+encodeURIComponent(endpoint), {
                    credentials: 'include'
                 })
       });
   }
 }).catch(function(err) {
   console.log(':^(', err);
 });
}

On the very first visit, this failes with:

Uncaught (in promise) DOMException: Subscription failed - no active Service Worker

From the second visit on, everything is OK because the ServiceWorker is already active at that time. Looks like this is a timing issue. How can I be sure the ServiceWorker has been registered successfully and is active before I try to subscribe to it?

I tried using navigator.serviceWorker.ready as suggested below:

if ('serviceWorker' in navigator) {
 console.log('Service Worker is supported');
 navigator.serviceWorker.register('/js/sw.js').then(function(sreg) {
   console.log(':^)', sreg);
   navigator.serviceWorker.ready.then(function(reg) {
       if(/chrom(e|ium)/.test(navigator.userAgent.toLowerCase())){
           reg.pushManager.subscribe({
               userVisibleOnly: true
           }).then(function(sub) {
               console.log('endpoint:', sub.endpoint);
               endpoint = sub.endpoint;
               fetch("https://www.wettfreun.de/?page=fetch&s=1&endpoint="+encodeURIComponent(endpoint), {credentials: 'include'})
           });
       }
   });
 }).catch(function(err) {
   console.log(':^(', err);
 });
}

Now the part inside navigator.serviceWorker.ready.then() is never called.

like image 906
Hokascha Avatar asked Mar 07 '16 15:03

Hokascha


People also ask

How do I find out if a service is already registered?

You can look at Service Worker Detector, a Chrome extension that detects if a website registers a Service Worker by reading the navigator. serviceWorker. controller property. It might also work in other browsers supporting Web Extensions, but it looks like it is not yet distributed as such.

How do I activate a service worker?

Updating your service workerIt is only activated when there are no longer any pages loaded that are still using the old service worker. As soon as there are no more such pages still loaded, the new service worker activates. While this happens, the previous version is still responsible for fetches.

What is the event when a service worker is ready to serve the request?

Once your service worker is ready to control clients and handle functional events like push and sync , you'll get an activate event.

What is service worker registration?

You register a service worker to control one or more pages that share the same origin. The lifetime of a service worker registration is beyond that of the ServiceWorkerRegistration objects that represent them within the lifetime of their corresponding service worker clients.


1 Answers

You can use ServiceWorkerContainer.ready.

Example from MDN:

function subscribe() {
  var subscribeButton = document.querySelector('.js-subscribe-button');
  subscribeButton.disabled = false;

  navigator.serviceWorker.ready.then(function(serviceWorkerRegistration) {
    serviceWorkerRegistration.pushManager.subscribe()
      .then(function(subscription) {
        // The subscription was successful
        subscribeButton.disabled = true;
        return sendSubscriptionToServer(subscription);
      })
      .catch(function(error) {
        if (Notification.permission === 'denied') {
          console.log('Permission for Notifications was denied');
          subscribeButton.disabled = true;
        } else {
          console.log('Unable to subscribe to push.', error);
          subscribeButton.disabled = false;
        }
      });
  });
}
like image 149
Marco Castelluccio Avatar answered Oct 10 '22 12:10

Marco Castelluccio