简体   繁体   English

如何为“ws”Web-Socket 模块创建自定义事件?

[英]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.是否可以为 NodeJS 中的“ws”websocket 模块创建自定义事件发射器和侦听器(就像 socket.io 中的那样)。 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);

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根据这篇文章,似乎可以接受的方式是使用像[eventname, data_object]这样的消息格式,然后解析它

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.我设法开始工作的是使用下面显示的内置addEventListener属性。

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.需要记住的是,socketio 有一个特殊的结构,你必须在使用 HTML5 WebSockets 时手动解析它。

You are able to do the same with the message event (and so on)您可以对message事件(等等)做同样的事情

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

Both WebSocket and WebSocketServer defined in ws package extends EventEmitter . ws package 中定义的WebSocketWebSocketServer都扩展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.因此,只要您有权访问EventEmitter或其扩展,就必须有一种方法可以使用标准 api 执行此操作。

TL;DR长话短说

I have forked and demonstrated a very simple way to achieve what the OP asks.我分叉并演示了一种非常简单的方法来实现 OP 的要求。 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.在服务器端,我为message事件创建了一个调度程序,它是客户端发出的所有事件的入口点,因此它可以根据客户端发出的事件发出事件。

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原型中添加了一个emit方法,方便向websocket服务端发送消息:

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 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 ).事实上,据我所知, WebSocketServer构造函数本身使用标准EventEmitter的方法在这里发出'connection'事件( this指的是WebSocketServer本身扩展了标准EventEmitter )。 But it seemingly uses addEventListeners in the following lines not on to attach listening , error , and upgrade events not standard on .但它似乎在以下行中使用addEventListeners not on 来附加非标准onlisteningerrorupgrade事件。 It might be building some abstractions and wrapping the way EventEmitter adds listeners, you might have use the way it does .它可能正在构建一些抽象并包装EventEmitter添加侦听器的方式,您可能已经使用了它的方式

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'.ws代码中的event-target.js addEventListener(type, listener, options = {})定义中,对于“message”、“error”、“open”和“close”以外的type参数, 此处返回未定义 So that code in the definition of constant EventTarget does not register the listener passed for event type .因此,常量EventTarget定义中的代码不会注册为事件type传递的listener器。 Also that EventTarget is not the Node.js standard EventTarget itself, just the name is same.此外,该 EventTarget 不是 Node.js 标准EventTarget本身,只是名称相同。

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.如果有或者您可以创建一种机制来将此处的代码块公开为实用程序,您可以将自定义事件属性添加为 getter 作为 setter,就像它为其自己的 web 套接字服务器事件属性所做的那样。 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 .但是,如果您这样做,请不要忘记在其原始位置使用原始事件名称数组调用它一次,因为它被调用以使用gettersetter将原始事件作为事件属性注册到WebSocket

There is also addListeners(server, map) and removeListeners() definitions in websocket-server.js but those are for WebSocketServer`. websocket-server.js中也有addListeners(server, map)removeListeners()定义,但这些是针对 WebSocketServer 的。

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");然后触发它,通过使用socket.emit("customEmit");

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM