I want to try run websockets in serviceWorker.
I write code for register serviceWorker:
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register(
GetDataForUser.settings.service_worker + "?version=" + GetDataForUser.settings.service_worker_version,
{scope: './'}
)
.then(() => navigator.serviceWorker
.ready
.then((worker) => {
console.log(worker);
worker.sync.register('syncdata');
})
)
.catch((err) => console.log(err));
navigator.serviceWorker.addEventListener('message', event => {
console.log('++++++++++++++++++++', event.data.msg, event.data.url);
});
}
And write serviceWorker code:
var ws = null;
self.addEventListener('install', (event) => {
console.log('Install');
});
self.addEventListener('activate', (event) => {
console.log('Activate');
ws = new WebSocket('ws://local.ll:8880');
ws.onopen = function() {
console.log("Open");
};
// On message receive
ws.onmessage = function (event) {
console.log("Message receive " + event.data);
console.log(event);
event.ports[0].postMessage({'test': 'This is my response.'});
};
// On error connection
ws.onerror = function (error) {
console.log("Error " + error.message);
};
// On close connection
ws.onclose = function (event) {
if (event.wasClean) {
console.log('clean closed');
} else {
console.log('broken connection');
}
console.log('Code: ' + event.code + ' reason: ' + event.reason);
};
});
self.addEventListener('fetch', (event) => {});
self.addEventListener('message', function (evt) {
console.log('postMessage received', evt.data);
ws.send('121212');
});
I try to send data to serviceWorker next:
navigator.serviceWorker.controller.postMessage({'hello': 'world'});
But receive an error:
Uncaught TypeError: Cannot read property 'postMessage' of null
console.log(navigator.serviceWorker);
ServiceWorkerContainer {controller: null, ready: Promise, oncontrollerchange: null, onmessage: null}
Trying to send message from serviceWorker to client next:
event.ports[0].postMessage({'test': 'This is my response.'});
But event.ports is empty.
Whats wrong? How to transfer data between client and serviceWorker.
To fix your error of controller being null, you need to add the activate event listener
self.clients.claim()
Without that, when the service worker is activated, the page is not controlled by it until the next navigation. This allows the service worker to take control of the pages as soon as it's active.
But I don't think it's your only problem. Looking at your code I think you're confusing WebSocket and MessageChannel. You seem to try to use WebSocket to send messages between client and service worker where you should be using MessageChannel for that.
For exemple if we want to send messages from the client to the SW and allow the SW to respond to those messages, we create a MessageChannel, and we send a port of this channel allong with the message for the SW to use in his response. in the client :
var msg = new MessageChannel();
msg.port1.onmessage = function(event){
//Response received from SW
console.log(event.data);
};
// Send message to SW
navigator.serviceWorker.controller.postMessage("hello", [msg_chan.port2]);
in the SW :
self.addEventListener('message', function(event){
//Message received from client
console.log(event.data);
//Send response to client using the port that was sent with the message
event.ports[0].postMessage("world");
});
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