Álvaro
Álvaro

Reputation: 2588

Send a custom event with ws

I am trying to listen to a custom event on the client with native websockets and with ws on the back end.

I first create a pool of connected clients.

import express from 'express'
import http from 'http'
import WebSocket from 'ws'
import { v4 as uuidv4 } from 'uuid'
import processes from './routes/process.js'
import { EventEmitter } from 'events'

// Express
const app = express()

// Initialize a simple http server
const server = http.createServer(app)

// Initialize the WebSocket server instance
const wss = new WebSocket.Server({ server })

let connections = {}

wss.on('connection', (socket) => {
  socket.id = uuidv4()
  connections[socket.id] = socket
  socket.send(socket.id)

  console.log(`Client connected ID: ${socket.id}`)

  socket.on('close', () => {
    delete connections[socket.id]
    delete socket.id
  })
})

And on react I store the socketID

const [socketID, setSocketID] = useState('')

useEffect(() => {
  const socket = new WebSocket('ws://localhost:4000')
  socket.onmessage = (message) => setSocketID(message.data)
}, [])

What I would like to do is then emit a message to the specific client using the socketID, I use axios from react to send the socketID in a request to an express route.

Then back at the server I use EventEmitter to pick up the client ID from the route, I have omitted the details cause is a bit lengthy, but at this point the server correctly identifies the client, the problem seems to be with sending a custom event.

connections[socketID].send('notify', 'Hello specific client')

And on the client I listen for the custom nofify event

useEffect(() => {
  const socket = new WebSocket('ws://localhost:4000')
  socket.onmessage = (message) => setSocketID(message.data)
  // Set notify listener to notify this specific client only
  socket.addEventListener('notify', (data) => {
    // I am expecting 'Hello specific client'
    console.log(data)
  })
}, [])

When I inspect react dev tools I can see that the socketID is receiving the 'custom event' and it changes the socketID to the word notify. So clearly ws is just sending the word notify and not as a custom event but as normal message that the client picks up as onmessage rather than the eventListener.

Upvotes: 4

Views: 5949

Answers (1)

Álvaro
Álvaro

Reputation: 2588

Since I cannot find anywhere anything about ws sending custom events, I just used the only send event to do everything, I have attached an event string to the message to know which one is been triggered.

Not ideal but it works. If anyone can think of a better way, please let me know.

wss.on('connection', (socket) => {
  socket.id = uuidv4()
  connections[socket.id] = socket
  socket.send(JSON.stringify({ event: 'ID', id: socket.id }))

  console.log(`Client connected ID: ${socket.id}`)

  socket.on('close', () => {
    delete connections[socket.id]
    delete socket.id
  })
})

connections[socketID].send(
  JSON.stringify({ event: 'notify', payload: 'Hello specific client')})
)
useEffect(() => {
  const socket = new WebSocket('ws://localhost:4000')

  socket.onmessage = (message) => {

    const data = JSON.parse(message.data)

    if (data.event === 'ID') {
      setSocketID(data.id)
    }

    if (data.event === 'notify') {
      console.log(data.payload)
    }
  }

}, [])

Upvotes: 3

Related Questions