tl;dr
A simple proxy wrapper to add state
event to WebSocket which will be emitted when its readyState
changes:
const WebSocketProxy = new Proxy(WebSocket, {
construct: function(target, args) {
// create WebSocket instance
const instance = new target(...args);
//internal function to dispatch 'state' event when readyState changed
function _dispatchStateChangedEvent() {
instance.dispatchEvent(new Event('state'));
if (instance.onstate && typeof instance.onstate === 'function') {
instance.onstate();
}
}
//dispatch event immediately after websocket was initiated
//obviously it will be CONNECTING event
setTimeout(function () {
_dispatchStateChangedEvent();
}, 0);
// WebSocket "onopen" handler
const openHandler = () => {
_dispatchStateChangedEvent();
};
// WebSocket "onclose" handler
const closeHandler = () => {
_dispatchStateChangedEvent();
instance.removeEventListener('open', openHandler);
instance.removeEventListener('close', closeHandler);
};
// add event listeners
instance.addEventListener('open', openHandler);
instance.addEventListener('close', closeHandler);
return instance;
}
});
A long explanation:
You can use a Proxy object to monitor inner WebSocket state.
This is a good article which explains how to do it Debugging WebSockets using JS Proxy Object
And here is an example of code snippet from the article above in case the site won't be available in the future:
// proxy the window.WebSocket object
var WebSocketProxy = new Proxy(window.WebSocket, {
construct: function(target, args) {
// create WebSocket instance
const instance = new target(...args);
// WebSocket "onopen" handler
const openHandler = (event) => {
console.log('Open', event);
};
// WebSocket "onmessage" handler
const messageHandler = (event) => {
console.log('Message', event);
};
// WebSocket "onclose" handler
const closeHandler = (event) => {
console.log('Close', event);
// remove event listeners
instance.removeEventListener('open', openHandler);
instance.removeEventListener('message', messageHandler);
instance.removeEventListener('close', closeHandler);
};
// add event listeners
instance.addEventListener('open', openHandler);
instance.addEventListener('message', messageHandler);
instance.addEventListener('close', closeHandler);
// proxy the WebSocket.send() function
const sendProxy = new Proxy(instance.send, {
apply: function(target, thisArg, args) {
console.log('Send', args);
target.apply(thisArg, args);
}
});
// replace the native send function with the proxy
instance.send = sendProxy;
// return the WebSocket instance
return instance;
}
});
// replace the native WebSocket with the proxy
window.WebSocket = WebSocketProxy;