[英]Socket.io Client: respond to all events with one handler?
Is it possible to have a socket.io client respond to all events without to have specify each event individually?是否可以让 socket.io 客户端响应所有事件而无需单独指定每个事件?
For example, something like this (which obviously doesn't work right now):例如,像这样的东西(显然现在不起作用):
var socket = io.connect("http://myserver");
socket.on("*", function(){
// listen to any and all events that are emitted from the
// socket.io back-end server, and handle them here.
// is this possible? how can i do this?
});
I want this callback function to be called when any / all events are received by the client-side socket.io code.我希望在客户端 socket.io 代码收到任何/所有事件时调用此回调函数。
Is this possible?这可能吗? How?
如何?
Updated solution for socket.io-client 1.3.7 socket.io-client 1.3.7的更新解决方案
var onevent = socket.onevent;
socket.onevent = function (packet) {
var args = packet.data || [];
onevent.call (this, packet); // original call
packet.data = ["*"].concat(args);
onevent.call(this, packet); // additional call to catch-all
};
Use like this:像这样使用:
socket.on("*",function(event,data) {
console.log(event);
console.log(data);
});
None of the answers worked for me, though the one of Mathias Hopf and Maros Pixel came close, this is my adjusted version.尽管 Mathias Hopf 和 Maros Pixel 的答案很接近,但没有一个答案对我有用,这是我调整后的版本。
NOTE: this only catches custom events, not connect/disconnect etc注意:这只捕获自定义事件,而不是连接/断开等
It looks like the socket.io library stores these in a dictionary.看起来 socket.io 库将这些存储在字典中。 As such, don't think this would be possible without modifying the source.
因此,不要认为在不修改源代码的情况下这是可能的。
EventEmitter.prototype.on = function (name, fn) {
if (!this.$events) {
this.$events = {};
}
if (!this.$events[name]) {
this.$events[name] = fn;
} else if (io.util.isArray(this.$events[name])) {
this.$events[name].push(fn);
} else {
this.$events[name] = [this.$events[name], fn];
}
return this;
};
Finally , there is a module called socket.io-wildcard which allows using wildcards on client and server side最后,还有一个名为socket.io-wildcard的模块,它允许在客户端和服务器端使用通配符
var io = require('socket.io')();
var middleware = require('socketio-wildcard')();
io.use(middleware);
io.on('connection', function(socket) {
socket.on('*', function(){ /* … */ });
});
io.listen(8000);
Here you go ...干得好 ...
var socket = io.connect();
var globalEvent = "*";
socket.$emit = function (name) {
if(!this.$events) return false;
for(var i=0;i<2;++i){
if(i==0 && name==globalEvent) continue;
var args = Array.prototype.slice.call(arguments, 1-i);
var handler = this.$events[i==0?name:globalEvent];
if(!handler) handler = [];
if ('function' == typeof handler) handler.apply(this, args);
else if (io.util.isArray(handler)) {
var listeners = handler.slice();
for (var i=0, l=listeners.length; i<l; i++)
listeners[i].apply(this, args);
} else return false;
}
return true;
};
socket.on(globalEvent,function(event){
var args = Array.prototype.slice.call(arguments, 1);
console.log("Global Event = "+event+"; Arguments = "+JSON.stringify(args));
});
This will catch events like connecting
, connect
, disconnect
, reconnecting
too, so do take care.这也会捕获
connecting
、 connect
、 disconnect
、 reconnecting
连接等事件,所以请务必小心。
Note: this answer is only valid for socket.io 0.x注意:此答案仅对 socket.io 0.x 有效
You can override socket.$emit您可以覆盖socket.$emit
With the following code you have two new functions to:使用以下代码,您有两个新功能:
var original_$emit = socket.$emit;
socket.$emit = function() {
var args = Array.prototype.slice.call(arguments);
original_$emit.apply(socket, ['*'].concat(args));
if(!original_$emit.apply(socket, arguments)) {
original_$emit.apply(socket, ['default'].concat(args));
}
}
socket.on('default',function(event, data) {
console.log('Event not trapped: ' + event + ' - data:' + JSON.stringify(data));
});
socket.on('*',function(event, data) {
console.log('Event received: ' + event + ' - data:' + JSON.stringify(data));
});
As it is in v3.0 documentation :就像在v3.0 文档中一样:
socket.onAny((event, ...args) => {
console.log(`got ${event}`);
});
The current (Apr 2013) GitHub doc on exposed events mentions a socket.on('anything')
.当前(2013 年 4 月)关于暴露事件的 GitHub 文档提到了
socket.on('anything')
。 It appears that 'anything' is a placeholder for a custom event name, not an actual keyword that would catch any event. 'anything' 似乎是自定义事件名称的占位符,而不是可以捕获任何事件的实际关键字。
I've just started working with web sockets and Node.JS, and immediately had a need to handle any event, as well as to discover what events were sent.我刚刚开始使用 Web 套接字和 Node.JS,并且立即需要处理任何事件,以及发现发送了哪些事件。 Can't quite believe this functionality is missing from socket.io.
不敢相信 socket.io 缺少这个功能。
socket.io-client 1.7.3 socket.io 客户端 1.7.3
As of May 2017 couldn't make any of the other solutions work quite how i wanted - made an interceptor, using at Node.js for testing purposes only:截至 2017 年 5 月,无法让任何其他解决方案完全按照我的意愿工作 - 制作了一个拦截器,仅在 Node.js 上用于测试目的:
var socket1 = require('socket.io-client')(socketUrl)
socket1.on('connect', function () {
console.log('socket1 did connect!')
var oldOnevent = socket1.onevent
socket1.onevent = function (packet) {
if (packet.data) {
console.log('>>>', {name: packet.data[0], payload: packet.data[1]})
}
oldOnevent.apply(socket1, arguments)
}
})
References:参考:
Because your question was pretty general in asking for a solution, I'll pitch this one that requires no hacking the code, just a change in how you use the socket.因为您的问题在寻求解决方案时非常笼统,所以我将提出这个不需要破解代码的问题,只需改变您使用套接字的方式即可。
I just decided to have my client app send the exact same event, but with a different payload.我刚刚决定让我的客户端应用程序发送完全相同的事件,但使用不同的有效负载。
socket.emit("ev", { "name" : "miscEvent1"} );
socket.emit("ev", { "name" : "miscEvent2"} );
And on the server, something like...在服务器上,类似...
socket.on("ev", function(eventPayload) {
myGenericHandler(eventPayload.name);
});
I don't know if always using the same event could cause any issues, maybe collisions of some kind at scale, but this served my purposes just fine.我不知道是否总是使用相同的事件会导致任何问题,也许是某种规模的碰撞,但这很好地满足了我的目的。
There is a long discussion about this topic going on at the Socket.IO repository issue page.在 Socket.IO 存储库问题页面上对此主题进行了长时间的讨论。 There are a variety of solutions posted there (eg, overriding EventEmitter with EventEmitter2).
那里发布了各种解决方案(例如,用 EventEmitter2 覆盖 EventEmitter)。 lmjabreu released another solution a couple weeks ago: a npm module called socket.io-wildcard that patches in a wildcard event onto Socket.IO (works with the current Socket.IO, ~0.9.14).
lmjabreu 几周前发布了另一个解决方案:一个名为socket.io-wildcard的 npm 模块,该模块将通配符事件修补到 Socket.IO(适用于当前的 Socket.IO,~0.9.14)。
Even though this is a old question, I have the same problem and solved using the native socket in Node.js
, which has a event of .on('data'), fired everytime some data comes.即使这是一个老问题,我也有同样的问题,并使用
Node.js
中的本机套接字解决了这个问题,它有一个 .on('data') 事件,每次数据到来时都会触发。 So this is what I've done so far:所以这就是我到目前为止所做的:
const net = require('net')
const server = net.createServer((socket) => {
// 'connection' listener.
console.log('client connected')
// The stuff I was looking for
socket.on('data', (data) => {
console.log(data.toString())
})
socket.on('end', () => {
console.log('client disconnected')
})
})
server.on('error', (err) => {
throw err;
})
server.listen(8124, () => {
console.log('server bound');
})
All methods I found (including socket.io-wildcard and socketio-wildcard) didn't work for me.我发现的所有方法(包括 socket.io-wildcard 和 socketio-wildcard)都不适合我。 Apparently there is no $emit in socket.io 1.3.5...
显然 socket.io 1.3.5 中没有 $emit ......
After reading socket.io code, I patched up the following which DID work:阅读 socket.io 代码后,我修补了以下 DID 工作:
var Emitter = require('events').EventEmitter;
var emit = Emitter.prototype.emit;
[...]
var onevent = socket.onevent;
socket.onevent = function (packet) {
var args = ["*"].concat (packet.data || []);
onevent.call (this, packet); // original call
emit.apply (this, args); // additional call to catch-all
};
This might be a solution for others as well.这也可能是其他人的解决方案。 However, ATM I don't exactly understand why nobody else seems to have issues with the existing "solutions"?!?
但是,ATM 我不完全理解为什么其他人似乎对现有的“解决方案”没有问题?!? Any ideas?
有任何想法吗? Maybe it's my old node version (0.10.31)...
也许这是我的旧节点版本(0.10.31)......
@Matthias Hopf answer @Matthias Hopf 回答
Updated answer for v1.3.5.更新了 v1.3.5 的答案。 There was a bug with args, if you wanna listen on old event and
*
event together.如果您想一起收听旧事件和
*
事件,则 args 存在错误。
var Emitter = require('events').EventEmitter;
var emit = Emitter.prototype.emit;
// [...]
var onevent = socket.onevent;
socket.onevent = function (packet) {
var args = packet.data || [];
onevent.call (this, packet); // original call
emit.apply (this, ["*"].concat(args)); // additional call to catch-all
};
I'm using Angular 6 and the npm package: ngx-socket-io我正在使用Angular 6和 npm 包: ngx-socket-io
import { Socket } from "ngx-socket-io";
... ...
constructor(private socket: Socket) { }
... ...
After connect the socket, I use this code, this is handling all custom events...连接套接字后,我使用此代码,这是处理所有自定义事件...
const onevent = this.socket.ioSocket.onevent;
this.socket.ioSocket.onevent = function (packet: any) {
const args = packet.data || [];
onevent.call(this, packet); // original call
packet.data = ["*"].concat(args);
onevent.call(this, packet); // additional call to catch-all
};
this.socket.on("*", (eventName: string, data: any) => {
if (typeof data === 'object') {
console.log(`socket.io event: [${eventName}] -> data: [${JSON.stringify(data)}]`);
} else {
console.log(`socket.io event: [${eventName}] -> data: [${data}]`);
}
});
In v4, Socket.IO has Catch-all listeners .在 v4 中,Socket.IO 有Catch-all listeners 。 For example:
例如:
socket.prependAny(() => {
console.log("This will be fired first");
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.