'How to create custom events for 'ws' Web-Socket module?

Is it possible to create a custom event emitter and listener (like there's in socket.io) for 'ws' websocket module in NodeJS. If so then, how can I achieve it?

// Here's what I wanna achieve (should work vice-versa):

// listening on server

WebSocket.on('connection', function (ws) {
  ws.on('myCustomEvent', function(data) {
    // do something with the data
  });
});

// emitting from client

socket.emit('myCustomEvent', data);


Solution 1:[1]

I'm new, but after a bit of searching the answer appears to be no.

It seems like the accepted way, according to this post, is to use a message format like [eventname, data_object] and then parse it

Solution 2:[2]

This is extremely old but I ran into this problem earlier today. What I managed to get working was to use the built in addEventListener property as displayed underneath.

ws.addEventListener('YourCustomEvent', (data) => {
    // data.data contains your forwarded data
    console.log(data.data)
})

Something to remember is that socketio has a special structure which you have to parse manually while using HTML5 WebSockets.

You are able to do the same with the message event (and so on)

ws.addEventListener('message', (data) => {
    // data.data contains your forwarded data
    console.log(data.data)
})

Solution 3:[3]

Both WebSocket and WebSocketServer defined in ws package extends EventEmitter. So there must be a way to do this with the standard api as long as you have access to EventEmitter or its extension.

TL;DR

I have forked and demonstrated a very simple way to achieve what the OP asks. It is here. Naming of the properties can be modified to achieve better and uniform naming.

On the server side I have made a dispatcher for message event which is the entry point of all events emitted from the client, so it can emit events based on the event emitted from the client.

ws.on("message", function (data) {
  const parsed = JSON.parse(data);
  const { eventName, payload } = parsed;
  ws.emit(eventName, payload);
});
// register your event handlers
ws.on("someEventName", function (data) {
  console.log("someEventName event happened. data: ", data);
});

Then I have registered my sample event handler for a sample event name. On the client side, I have added an emit method to the WebSocket prototype to conveniently send messages to the websocket server:

WebSocket.prototype.emit = function (eventName, payload) {
  this.send(JSON.stringify({eventName, payload}));
}
...
ws.onopen = function (event) {
  // when connection to websocket server is opne you can emit any event with the following mentohd and signature.
  ws.emit('someEventName', {a: 1, b: 2});
}

END of TL;DR

Some observation I have made in the code base which might be correct to some degree:

Indeed, the WebSocketServer constructor itself uses standard EventEmitter's method to emit a 'connection' event here, as far as I can understand (this there refers to the WebSocketServer itself extends standard EventEmitter). But it seemingly uses addEventListeners in the following lines not on to attach listening, error, and upgrade events not standard on. It might be building some abstractions and wrapping the way EventEmitter adds listeners, you might have use the way it does.

In the event-target.js addEventListener(type, listener, options = {}) definition in ws code returns undefined here for type parameter other than 'message', 'error', 'open', and 'close'. So that code in the definition of constant EventTarget does not register the listener passed for event type. Also that EventTarget is not the Node.js standard EventTarget itself, just the name is same.

If there is or you can create a mechanism to expose the code block here as a utility you can add custom event attributes as getters as setters in the same way it does for its own web socket server event attributes. But if you do this do not forget to call it with the original array of event names once in its original place as it is called to register the original events as event atttributes to the WebSocket with a getter and setter.

There is also addListeners(server, map) and removeListeners() definitions in websocket-server.js but those are for WebSocketServer`.

Solution 4:[4]

const websocket = require('ws');
const socket = new websocket.Server(options);
socket.on("customEmit", (ws, req) => {
    console.log("custom event");
});

And then trigger it, by using socket.emit("customEmit");

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Alter
Solution 2 Yazaar
Solution 3
Solution 4 Kirill A