I try to postMessage
between a web application and the corresponding service worker. The service worker is successfully registered and working so far.
Unfortunately, I noticed some strange behavior:
navigator.serviceWorker.controller
is always null
.postMessage
as follows:self.addEventListener('message', function (evt) {
console.log('postMessage received', evt);
});
Unfortunately, the important fields to post back to the origin evt.origin=''
and evt.source=null
do not contain the desired values. Nonetheless, I always received the sent evt.data
.
Do you know how to post back?
Thank you very much!
Andi
postMessage() is a safe way to send messages between windows in different domains or origins. One can also post to an IFrame. The data being sent is serialized using the structured clone algorithm and will accept almost any type of simple or complex data.
The postMessage() method of the Client interface allows a service worker to send a message to a client (a Window , Worker , or SharedWorker ). The message is received in the " message " event on navigator. serviceWorker .
@GalBracha was asking if you could communicate with the client without first sending a message - yes!. Here's a quick example of how I did it when I wanted to send a message to clients when a push notification was received (not when the user clicked on the notification, but when the service worker received the event):
in your client js (after service worker registration, etc):
// navigator.serviceWorker.addEventListener('message', ... ) should work too
navigator.serviceWorker.onmessage = function (e) {
// messages from service worker.
console.log('e.data', e.data);
};
in your service worker, in response to some event (perhaps the install event):
// find the client(s) you want to send messages to:
self.clients.matchAll(/* search options */).then( (clients) => {
if (clients && clients.length) {
// you need to decide which clients you want to send the message to..
const client = clients[0];
client.postMessage("your message");
}
the trick is (obviously?) to attach your listener for the message event to the serviceWorker object, not the window object.
Sending information back and forth between a service worker and its client is much easier using the Broadcast Channel API, compared to other methods.
Define a new broadcasting channel in both the service worker and the client.
const channel4Broadcast = new BroadcastChannel('channel4');
To send a broadcast message in either the worker or the client:
channel4Broadcast.postMessage({key: value});
To receive a broadcast message in either the worker or the client:
channel4Broadcast.onmessage = (event) => {
value = event.data.key;
}
Broadcasting also allows sending messages between web workers of the client, the client and the service worker.
This simplicity comes at a price though. As it currently stands, the service worker will not wake up to receive broadcast messages. Therefore, it only works when the service worker is in a running (active or waiting) state; i.e. when the client is visible. Nonetheless, this may still be useful, for example to broadcast version numbers or web pushes, etc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With