trasherdk / ws

Simple to use, blazing fast and thoroughly tested WebSocket client and server for Node.js
MIT License
0 stars 0 forks source link

Reminder: Offloading to worker-thread & Class implementation #6

Closed trasherdk closed 6 months ago

trasherdk commented 2 years ago

Just something to try. Show implementation of Class Socket() as a worker-thread.

I don't see how this connects to a wss instance, but I might later :smile:

socket-worker.js

// socket-worker.js
'use strict'

const { Worker } = require('worker_threads')
const path = require('path')

class Socket {
  constructor(url) {
    this._worker = new Worker(path.join(__dirname, 'socket-worker.js'), {
      workerData: {
        url: url.href,
      },
    })
      .on('error', (err) => {
        this.onerror?.(err)
      })
      .on('exit', () => {
        this.readyState = this.CLOSED
      })
      .on('message', ({ event, data }) => {
        if (event === 'open') {
          this.readyState = this.OPEN
          this.onopen?.()
        } else if (event === 'error') {
          this.readyState = this.CLOSING
          this.onerror?.(data)
        } else if (event === 'close') {
          this.readyState = this.CLOSED
          this.onclose?.()
        } else if (event === 'data') {
          this.onmessage?.({ data: Buffer.from(data) })
        }
      })

    this.CONNECTING = 'CONNECTING'
    this.OPEN = 'OPEN'
    this.CLOSING = 'CLOSING'
    this.CLOSED = 'CLOSED'

    this.onopen = null
    this.onerror = null
    this.onclose = null
    this.onmessage = null
    this.readyState = this.CONNECTING
  }

  send(data) {
    // TODO (perf): Transfer Buffer?
    this._worker.postMessage(data)
  }

  close() {
    this.readyState = this.CLOSING
    this._worker.terminate()
  }
}

module.exports = Socket

socket.js

// socket.js
'use strict'

const { Worker } = require('worker_threads')
const path = require('path')

class Socket {
  constructor(url) {
    this._worker = new Worker(path.join(__dirname, 'socket-worker.js'), {
      workerData: {
        url: url.href,
      },
    })
      .on('error', (err) => {
        this.onerror?.(err)
      })
      .on('message', ({ event, data }) => {
        if (event === 'open') {
          this.readyState = this.OPEN
          this.onopen?.()
        } else if (event === 'error') {
          this.readyState = null
          this.onerror?.(data)
        } else if (event === 'close') {
          this.readyState = null
          this.onclose?.()
        } else if (event === 'data') {
          this.onmessage?.({ data: Buffer.from(data) })
        }
      })

    this.OPEN = 'OPEN'

    this.onopen = null
    this.onerror = null
    this.onclose = null
    this.onmessage = null
    this.readyState = null
  }

  send(data) {
    // TODO (perf): Transfer Buffer?
    this._worker.postMessage(data)
  }

  close() {
    this._worker.terminate()
  }
}

module.exports = Socket