Reputation: 125
I'm utilizing websockets for passing json messages but I don't want multiple ws connections if multiple tabs are open.
To reduce the connections I want to implement a single ws connection object that can send/receive messages to and from all tabs to my website. The object should forward the json to all tabs and each tab will process the message.
I've been looking at web/shared/service workers and I'm not sure the 2018 path to solve the issue and browser support seems to be a concern as well.
Looks like shared workers are not supported in Safari in support of service workers. Chrome/ff/opera seem to support shared workers.
In short it's a little confusing, bit of a mess and I want to know the best path forward with the best support.
If you know of a good resource, example code to implement ws with your suggested method please provide it as well.
Upvotes: 2
Views: 904
Reputation: 125
After further research I've decided to implement web workers.
At this point I'm having success and I wanted to add an important piece that I got stuck on for future readers.
In my worker.js file I put this at the top to kick things off. The importScripts function threw an error if I didn't do it otherwise.
Also for the sake of helping, this is my skeleton code in my worker.js file that works. Message processing from the html pages are separated from the ws messages received from the server. You can start, stop the worker from the html page.
All tabs will get the messages from the worker, each page needs to process the messages as needed.
I'm also using robust-websockets so it auto reconnects from this github as this code works with web workers and is maintained. There is another project by the same name that isn't as updated by the time of this post. The reconnecting-websockets does not support web workers and you will get an error. - https://github.com/nathanboktae/robust-websocket
html
<script>
document.addEventListener('DOMContentLoaded', init);
function init(){
worker = new Worker('js/ws_worker.js');
worker.addEventListener('message', workerMessaged);
worker.postMessage({ "args": '<username_admin>', "cmd": 'start', "url": '127.0.0.1:8000' });
worker.postMessage({ "message": 'Initialize new worker'});
console.log('Message posted to worker, start');
}
// Received a json message from the Worker, process it.
function workerMessaged(ev){
console.log('Message received from worker');
console.log(ev.data);
worker.postMessage({ "cmd": 'message', "message": 'Sending reply over ws'});
}
worker.js
// proper initialization
if( 'function' === typeof importScripts) {
importScripts('robust-websocket.js');
var WebSocket;
self.addEventListener("message", function(e) {
var args = e.data.args;
var cmd = e.data.cmd;
var roomName = e.data.args;
var url = e.data.url;
var message = e.data;
// Code to process ws messages from the server
WebSocket.onmessage = function(event) {
console.log(" WebSocket message received: " + event.data, event);
self.postMessage(event.data);
};
WebSocket.onerror = function(event) {
console.log(" WebSocket message received: " + event.data, event);
self.postMessage(event.data);
};
if (cmd === 'start') {
WebSocket = new RobustWebSocket(
'ws://' + url +
'/ws/' + roomName + '/');
console.log('Connected via websockets');
/* Send initial message to open the connection and finalize the ws object*/
WebSocket.onopen = function() {
var obj = { "message": "hello" };
var json = JSON.stringify(obj);
WebSocket.send(json);
};
} else if (cmd === 'stop') {
WebSocket.onclose = function() {
console.log('Closing WebSocket');
WebSocket.close();
console.log('Closed WebSocket');
console.log('Terminating Worker');
self.close(); // Terminates the worker.
};
} else if (cmd === 'message') {
WebSocket.onopen = function() {
var json = JSON.stringify(message);
WebSocket.send(json);
};
console.log('message sent over websocket');
console.log('message');
} else {
console.log('logging error ' + e.data);
console.log(e.data);
self.postMessage('Unknown command: ');
}
}, false);
};
Upvotes: 1