How do I call a method on my ServiceWorker from my page?

I have a ServiceWorker registered on my page, and I want to transfer some data to it so that it can be saved in IndexedDB and used later for network requests (this is an access token).

Is it right to use network requests and catch them on the SW side with fetch, or is there something smarter?

Note for future readers interested in similar things for me:

Setting properties of the SW registration object, for example. by setting self.registration.foo to a function inside the service worker and doing the following on the page:

navigator.serviceWorker.getRegistration().then(function(reg) { reg.foo; }) 

Results in 'TypeError: reg.foo is not a function'. I believe this is related to the ServiceWorker life cycle, which means you cannot modify it and expect these modifications to be available in the future, so any interface with SW should probably have a postMessage style, so maybe just using sampling the best way to go ...?

+8
service-worker
source share
2 answers

So it turns out that you cannot actually call the method in SW from your application (due to lifecycle issues), so you need to use the PostMessage API to send serialized JSON messages (so no callbacks, etc. ) ,.

You can send a message to the management software with the following application code:

 navigator.serviceWorker.controller.postMessage({'hello': 'world'}) 

In the SW code in combination with the following:

 self.addEventListener('message', function (evt) { console.log('postMessage received', evt.data); }) 

As a result, on the SW console, you get the following:

 postMessage received Object {hello: "world"} 

Thus, by passing a message (JS object) that points to a function and the arguments that I want to call my event listener, we can get it and call the correct function in SW. To return the result to the application code, you also need to transfer the MessageChannel port to SW, and then respond via postMessage, for example, in the application that you created and sent via MessageChannel with data:

 var messageChannel = new MessageChannel(); messageChannel.port1.onmessage = function(event) { console.log(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(message, [messageChannel.port2]); 

and then you can answer through it with your Worker Worker in a message handler:

 evt.ports[0].postMessage({'hello': 'world'}); 
+14
source share

To transfer data to your service representative, the above is a good way. But in case it’s still difficult for someone to implement this, there’s another hack for this,

1 - add your data to get the parameter at the time of loading the service worker (for example, from sw.js β†’ sw.js?a=x&b=y&c=z )

2- Now in the service worker select this data using self.self.location.search .

Please note that this will be useful only if the data that you transmit does not change very often for a particular client, but, nevertheless, it will continue to change the URL of the service being downloaded for that particular client and every time, when the client reboots or a new service worker reappears.

0
source share

All Articles