Skip to content

Catch error in ws.send when WebSocket is not in an open-state #12

@roerdinkholder

Description

@roerdinkholder

When using this API, occassionally (~once a day), my application crashes due to the API trying to send over the websocket while the websocket is in a closed state:

\node_modules\ws\lib\websocket.js:329
  const err = new Error(

Error: WebSocket is not open: readyState 3 (CLOSED)
  at WebSocket.send (\node_modules\ws\lib\websocket.js:329:19)
  at doSendPublic (\node_modules\bitvavo\node-bitvavo-api.js:88:8)
  at Object.subscriptionTicker (\node_modules\bitvavo\node-bitvavo-api.js:857:9)

Due to the asynchronous nature of the ticker subscription, I cannot catch the thrown exception in my own code as far as I'm aware, so I'm a sitting duck for these crashes. The problem occurs in the following piece of code:

  const doSendPublic = function (ws, message) {
    debugToConsole('SENT: ' + message)
    ws.send(message)
  }

  const doSendPrivate = function (ws, message) {
    if (apiKey === '') {
      errorToConsole('You did not set the API key, but requested a private function.')
      return
    }
    if (this.authenticated) {
      debugToConsole('SENT: ' + message)
      ws.send(message)
    } else {
      waitForSocketPrivate(ws, () => {
        debugToConsole('SENT: ' + message)
        ws.send(message)
      })
    }
  }

The three ws.send commands should either pass a callback as third parameter, or be wrapped in a try-catch-block, to intercept the error. I'm willing to write a PR if you want. ws.send signature:

  /**
   * Send a data message.
   *
   * @param {*} data The message to send
   * @param {Object} options Options object
   * @param {Boolean} options.compress Specifies whether or not to compress `data`
   * @param {Boolean} options.binary Specifies whether `data` is binary or text
   * @param {Boolean} options.fin Specifies whether the fragment is the last one
   * @param {Boolean} options.mask Specifies whether or not to mask `data`
   * @param {Function} cb Callback which is executed when data is written out
   * @public
   */
  send(data, options, cb) {

This triggers the error in the ws.send method:

    if (this.readyState !== WebSocket.OPEN) {
      const err = new Error(
        `WebSocket is not open: readyState ${this.readyState} ` +
          `(${readyStates[this.readyState]})`
      );

      if (cb) return cb(err);
      throw err;
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions