Reputation: 2588
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
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