Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Service Worker not receiving message

NOTE: Using Create-React-App Template... (Modifying the Service Worker in it)

I am using the communication channel api to send a message to a service worker for caching. I use an xmlhttp request because of its progress api since fetch needs an indefinite loader afaik.

So after receiving the data on readystate 4 and status code 200 I go to postMessage to SW. I get logging on client side but don't receive the message in the service worker.

I am developing locally and using a Chrome Extension to allow local testing of SW and Build: https://chrome.google.com/webstore/detail/web-server-for-chrome/ofhbbkphhbklhfoeikjpcbhemlocgigb?hl=en

CLIENT SNIPPET

xhr.onreadystatechange = function(){
    if (this.readyState == 4 && this.status == 200) {
        const res = JSON.parse(this.responseText);

        function sendMessage(msg){
            console.log("SEND SW MESSAGE");
            const msgChan = new MessageChannel();
            // This wraps the message posting/response in a promise, which will resolve if the response doesn't
            // contain an error, and reject with the error if it does. If you'd prefer, it's possible to call
            // controller.postMessage() and set up the onmessage handler independently of a promise, but this is
            // a convenient wrapper.
            return new Promise(function(resolve, reject){
                console.log("Promise Scope");

                msgChan.port1.onmessage = function(event){
                    event.data.error ? reject(event.data.error) : resolve(event.data);
                }
                // This sends the message data as well as transferring messageChannel.port2 to the service worker.
                // The service worker can then use the transferred port to reply via postMessage(), which
                // will in turn trigger the onmessage handler on messageChannel.port1.
                // See https://html.spec.whatwg.org/multipage/workers.html#dom-worker-postmessage
                navigator.serviceWorker.controller.postMessage(msg, [msgChan.port2]);
            });
        }

        sendMessage(res).then(function(){
            console.log("SW MESSAGE SENT");
            // Storing Quake Data
            that.props.setQuakes(res[0]);
            // Storing Three Data Obj - SSR Parsing and Creation
            that.props.setThreeData(res[1]);   
            // Greenlight 
            that.props.setVizInitSuccess(true);
        }).catch(function(err){
            console.log("Error Caching Data: "+err);
        });
    } };

SERVICE WORKER SNIPPET

function registerValidSW(swUrl, config) {
  navigator.serviceWorker
    .register(swUrl)
    .then(registration => {
      // Set up a listener for messages posted from the service worker.
      // The service worker is set to post a message to all its clients once it's run its activation
      // handler and taken control of the page, so you should see this message event fire once.
      // You can force it to fire again by visiting this page in an Incognito window.
      navigator.serviceWorker.onmessage = function(event) {
        console.log("SERVICE WORKER RECIEVED MESSAGE");
        console.log(event);

        event.ports[0].postMessage("SW Says Hello Back!");
        if (event.data.requireData == true && 'caches' in window) {
          // Check for cache'd data and load
          // clients.matchAll().then(clients => {
          //     clients.forEach(client => {
          //         console.log(client);
          //         //send_message_to_client(client, msg).then(m => console.log("SW Received Message: "+m));
          //     })
          // })

          // caches.open('threeData').then(function(cache){
          //   console.log("SW Cache");
          //   console.log(cache)
          //   event.ports[0].postMessage(cache);  
          // });

        } else {
          // Cache Data
          caches.open('threeData').then(function(cache){
            cache.put('/data.json', new Response(event.data.json))
          });
        }
      };
...
like image 626
Michael Paccione Avatar asked Jul 25 '19 02:07

Michael Paccione


People also ask

How do you check if a service worker is running or not?

A: From a page on the same origin, go to Developer Tools > Application > Service Workers. You can also use chrome://inspect/#service-workers to find all running service workers.

How do you send a message to a service worker?

Controlled pages can use the ServiceWorker. postMessage() method to send messages to service workers. The service worker can optionally send a response back via the Client. postMessage() , corresponding to the controlled page.

How do you update a service worker?

update() The update() method of the ServiceWorkerRegistration interface attempts to update the service worker. It fetches the worker's script URL, and if the new worker is not byte-by-byte identical to the current worker, it installs the new worker.


1 Answers

navigator used in Service Worker file is WorkerNavigator Interface and not Navigator Interface.

WorkerNavigator is a subset of the Navigator interface allowed to be accessed from a Worker (In this case its Service worker). WorkerNavigator Reference.

So navigator inside Service worker file doesn't contains serviceWorker object. So it throws error when you call navigator.serviceWorker.onMessage.

To receive the messages from client use self.addEventListener in Service Worker file.

self.addEventListener('message', event => {
  console.log(`[Message] event: `, event.data);
});
like image 159
Sivanesh S Avatar answered Sep 29 '22 01:09

Sivanesh S