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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions