3

My web app needs to periodically check if the server is up. This allows users to start the server and client in either order.

To do this, I'm simply calling the WebSocket constructor from inside a setTimeout handler.

This strategy works well from a usage standpoint, but it is annoying for me the developer, because I see a lot of console errors in Chrome:

remote.html:194 WebSocket connection to 'ws://localhost:8082/' failed: Connection closed before receiving a handshake response
remote.html:194 WebSocket connection to 'ws://localhost:8082/' failed: Connection closed before receiving a handshake response
remote.html:194 WebSocket connection to 'ws://localhost:8082/' failed: Connection closed before receiving a handshake response

These are not really errors because my web app is perfectly fine with the server being unavailable. It is repeatedly calling the WebSocket constructor (MDN) merely to check if the server has been started yet.

Is there a better way to do this? For context, my web app is a "remote control" for a native C++ app that runs on a device.

prideout
  • 2,895
  • 1
  • 23
  • 25
  • So is the only problem to filter messages out of the Console section of Chrome or also from your Terminal and logs? – Gh05d Mar 12 '21 at 10:54

4 Answers4

8

Errors are suppressed when using a SharedWorker! Try the following:

main.html

<!doctype html>
<html>
  <head>
    <title>WS Test</title>
    <script type="text/javascript"> (async () => {
      
      await new Promise(r => window.addEventListener('load', r));
            
      let worker = new SharedWorker('worker.js');
      worker.port.onmessage = evt => console.log('MSG:', evt.data);
      
    })() </script>
  </head>
  <body></body>
</html>

worker.js

let ports = [];
onconnect = ({ ports: [ port ] }) => ports.push(port);

(async () => {
  
  while (true) {
    
    await new Promise(r => setTimeout(r, 1000));
    
    let ws = new WebSocket('ws://localhost:9999/');
    ws.addEventListener('error', evt => ports.forEach(port => port.postMessage('error')));
    ws.addEventListener('open', evt => ports.forEach(port => port.postMessage('open')));
    
  }
  
})();

This gives me feedback that the WebSocket is hitting an Error, but doesn't produce any additional noise in the logs: console showing ws errors with no additional noise

(Note that "some messages have been moved to the issues panel" is due to the hasty standards-incompliant test html - it will go away if you transfer this solution to your own code!)

A SharedWorker has no necessary link to any particular tab - for this reason I can see no justification why a SharedWorker's errors could ever appear as noise in a tab's console in any environment.

Gershom Maes
  • 7,358
  • 2
  • 35
  • 55
1

Please notice that connection error messages are mostly handled by the browser itself, not JS runtime.

If you wand to explicitly suppress runtime errors, you can use onerror event handler. Example:

window.onerror = function(message, url, lineNumber) {
        // you can also filter out certain messages in this handler
        return true; // prevents all error messages from displaying
};

Also, consider to use something like setting up health check HTTP endpoint, instead of opening WS connection.

As your error messages state, your are closing connection right after opening, you should not do that, instead you can keep one WS connection open and use ping/pong WebSocket messages to check if connection is alive, thus ensuring that server is alive too. If the connection is closed, you can periodically retry to connect with setInterval, and if connection attempt is successful, reuse previous WS object variable and destroy interval with clearInterval.

vkml
  • 36
  • 4
  • Thanks! Yes I might need to work around this with an `onerror` handler but I was hoping for a better solution. I am not calling `close()` anywhere, despite what the error message says. I believe this is being done implicitly, because the HTML Standard says: ``` If the establish a WebSocket connection algorithm fails, it triggers the fail the WebSocket connection algorithm, which then invokes the close the WebSocket connection algorithm ``` I think your health check idea is not applicable in my case, since the server is embedded inside a native C++ app that runs on a device. – prideout Mar 08 '21 at 17:58
  • 1
    Just now did an experiment: in Chrome 88 (macOS), `window.onerror` is not triggered when a WebSocket connection fails. This was a good idea though. – prideout Mar 08 '21 at 18:11
  • @prideout but you are trying to establish a WS connection with that server that is embedded inside a native C++ app that runs on a device, right? To establish WS connection, client sends HTTP GET request with proper headers and server responses with HTTP 101 status code (switching protocol, if I remember right), this stage is also called handshake. Why is that a problem to use just one HTTP request, instead of performing handshake and protocol upgrade? – vkml Mar 09 '21 at 08:23
  • @prideout anyway, you can also remove console records with `console.clear` function, if this suits you – vkml Mar 09 '21 at 08:35
  • Your understanding of my problem's context is correct. Yes, I can poll for the server using HTTP GET, but then I have the same issue of seeing annoying error messages in the Chrome console. Thanks for your help, these are all good ideas. I feel this is an oversight in the standard -- what's I'm trying to do isn't crazy. – prideout Mar 10 '21 at 00:18
  • @prideout thanks for an interesting question though. Try to check the second answer from [this question](https://stackoverflow.com/questions/43012334/silence-neterr-connection-refused), maybe this crazy "solution" will help – vkml Mar 10 '21 at 07:18
1

All error is suppressed but this cannot be below is the reason

WebSocket connection to 'ws://localhost:5000/tech-support' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED

There is no way to trap that error message, which occurs asynchronously to the code where the WebSocket object is created.

More details here: Javascript doesn't catch error in WebSocket instantiation

Gh05d
  • 7,923
  • 7
  • 33
  • 64
Syed Mohib Uddin
  • 718
  • 7
  • 16
-1

Websockets are just upgraded HTTP/HTTPS Endpoints, so you can do a request and check if you can upgrade

Jytesh
  • 815
  • 4
  • 15