I am late to the party, but for anyone landing on this page for the same problem, here is the answer:
In simple terms, closing a WebSocket connection involves negotiation between the server and the client. The one attempting to close the connection sends a close frame to the other party. Then, the other party acknowledges the request. Hence, both parties (server and client) know about the connection closure, and therefore, the close event is fired by the web browsers.
But when the connection link itself gets broken (disconnecting internet from PC), both the parties remain unaware of the disconnect. That's why the close event is not fired by the browser.
The solution is to ping the server at regular intervals. If you do not receive a response from the server within some specific amount of time, then you know that the connection link is broken.
The WebSocket spec has ping and pong frames that can be used, but the JavaScript WebSocket API in web browsers doesn't expose those (yet). So, you can send any dummy message (such as 'ping') to the server and configure the server to reply with some text in response to that particular message (such as 'pong').
Create a variable in your JavaScript code to keep the server status (alive/dead). When a message is received, set the alive status to true. After every few intervals, check the status. If alive status is true, set it to false. If the alive status is false during the next setInterval execution, then you know that the link is broken (or the server is not responding).
Example code (you can customize the time intervals, but the ping interval should not be greater than the checking interval):
ws.addEventListener('open', () => {
ws.alive = true;
});
ws.addEventListener('close', () => stopPing());
ws.addEventListener('message', () => ws.alive = true);
//Ping
setInterval(() => ws.send('ping'), 1000); //Send ping to server every second
//Check
setInterval(() => {
if (!ws.alive) {
//Link broken
} else {
ws.alive = false;
}
}, 5000); //Check every 5 seconds
Server side:
ws.on('message', message => {
message = message.toString();
if(message == 'ping') ws.send('pong');
});