2

The setup

I am using the websockets/ws library to listen to a WSS feed. It works well, it's lightweight enough and it seems to be one of the fastest around (which is important).

I'm trying to differentiate between me programmatically closing the connection, and them closing it for whatever reason.

According to the docs, I can send a code (int) and a reason (string), both of which are sent to the on close event. But by all accounts, this functionality no longer exists.

Tests

  • Most codes throw a First argument must be a valid error code number error
  • Leaving it blank sends code = 1005 and an empty reason to the event
  • If I enter a code of 1005, I get the invalid error
  • If I enter a code of 1000, the event receives code = 1006 and still an empty reason (regardless of what I put)

^ tests are simple enough...

var WebSocket = require('ws');

var ws = new WebSocket(url);
ws.on('close', function(code, reason) {
    console.log(code);
    console.log(reason);
});

var code = 1234, 
    reason = 'whatever reason';

setTimeout(function() {
    ws.close(code, reason);
}, 5000);

But...

I need to be able to tell if I've closed the connection, or if it was closed for another reason (connection lost, they closed it because of time limits, etc). Depending on the reason it was closed, I sometimes need to immediately reopen the connection, but only sometimes.

I can do something like...

_initWS(url) {
    var ws = new WebSocket(url);

    ws.on('open', function() {...});

    ws.on('close', function(code, reason) {
        ws = null;          // Don't know if needed
        ws = _initWS(url);  // Reopen the connection, for ever and ever...
    });

    ws.on('message', funciton(msg) {...});

    return ws;
}

var someFeed = _initWS(someURL);

... but since the code and reason are all but meaningless, this automatically restarts the connection regardless of why it was closed. This is great if the connection was lost or timed-out, but not so great if I want to close it programmatically...

someFeed.close(); // Connection immediately reopens, always and forever

Question(s)

How can I differentiate between different closes? I don't want to change the library code, because then I can't use npm install when I move my own code around. Can I override the close method within my own code?

Or is there an equally lightweight and lightning-fast library that has the functionality I'm looking for? I just need to be able to reliably send a unique code and/or reason, so I know when I'm trying to close it manually. I know that asking for recommendations is taboo, but there are too many libraries to test each one, and no benchmarks that I can find.

Birrel
  • 4,754
  • 6
  • 38
  • 74
  • Just remember whether you wanted it closed or not. – Bergi Feb 12 '18 at 18:57
  • @Bergi What do you mean? – Birrel Feb 12 '18 at 18:58
  • 2
    When you are programmatically closing the connection from your side, you should know that you did and probably you can check whether the reason for it still exists. Or just use a boolean flag. – Bergi Feb 12 '18 at 19:00
  • @Bergi I don't know if I quite understand. Regardless of *why* it closes, it will have to pass through the `close` event - which is where I need to automatically reopen the connection from other closures. The only way I can close it is `.close()`, which then triggers the `close` event, and it reopens. I could put a condition in the `close` event, but I can't send anything to it, through `.close()` – Birrel Feb 12 '18 at 19:03

1 Answers1

3

From the suggestion from @Bergi

_initWS(url) {
    var ws = new WebSocket(url);

    ws.didIClose = false;  // This is the flag to set if I close it manually

    ws.forceClose = function() {
        ws.didIClose = true;
        ws.close();
    };

    ws.on('open', function() {...});

    ws.on('close', function(code, reason) {
        if(!ws.didIClose) {    // If I didn't close it, reopen
            ws = null;          
            ws = _initWS(url);  
        }

    });

    ws.on('message', funciton(msg) {...});

    return ws;
}

var someFeed = _initWS(someURL);

And then to use it...

someFeed.didIClose = true;
someFeed.close();    // Won't reopen the connection

Or, a bit cleaner...

someFeed.forceClose();

Edit #1

Modified solution to include the forceClose() method - requiring only one clean line of code to programmatically close it (instead of two).

Birrel
  • 4,754
  • 6
  • 38
  • 74
  • 1
    Yes, exactly like that. Btw, the `ws = null` before the other assignment is indeed pointless. – Bergi Feb 12 '18 at 21:33