Socket.io客户端:用一个处理程序响应所有事件?

是否有可能有一个socket.io客户端响应所有事件,而不必单独指定每个事件?

例如,像这样的东西(这显然现在不工作):

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? }); 

我想要在客户端socket.io代码接收到任何/所有事件时调用此callback函数。

这可能吗? 怎么样?

它看起来像socket.io库存储在一个字典中。 因此,不要认为这是不可能的,而不需要修改源代码。

来源 :

 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; }; 

更新了socket.io-client 1.3.7的解决scheme

 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 }; 

像这样使用:

 socket.on("*",function(event,data) { console.log(event); console.log(data); }); 

没有答案为我工作,虽然Mathias Hopf和Maros Pixel之一接近,这是我的调整版本。

注意:这只捕获自定义事件,不连接/断开连接等

干得好 …

 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)); }); 

这将捕获connectingconnectdisconnectreconnecting connect等事件,所以要小心。

注意:这个答案只对socket.io 0.x有效

你可以覆盖socket。$ emit

用下面的代码你有两个新的function:

  • 捕获所有事件
  • 仅捕获未被旧方法捕获的事件(它是默认侦听器)
 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)); }); 

最后 ,有一个叫做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); 

目前(2013年4月) 关于暴露事件的GitHub doc提到了socket.on('anything') 。 看起来,“任何事物”是一个自定义事件名称的占位符,而不是一个可以捕获任何事件的实际关键字。

我刚刚开始使用Web套接字和Node.JS,并立即需要处理任何事件,以及发现发送的事件。 不能相信这个function从socket.io中丢失。

关于在Socket.IO存储库问题页面上进行的这个话题有一个很长的讨论 。 在那里发布了各种解决scheme(例如,用EventEmitter2覆盖EventEmitter)。 lmjabreu在几个星期前发布了另一个解决scheme:一个名为socket.io-wildcard的npm模块,将通配符事件打包到Socket.IO(与当前Socket.IO,〜0.9.14协同工作)。

因为你的问题在寻求解决scheme时是相当普遍的,所以我将介绍这个不需要破解代码的东西,只是改变你如何使用套接字。

我只是决定让我的客户端应用程序发送完全相同的事件,但有不同的有效载荷。

 socket.emit("ev", { "name" : "miscEvent1"} ); socket.emit("ev", { "name" : "miscEvent2"} ); 

在服务器上,像…

 socket.on("ev", function(eventPayload) { myGenericHandler(eventPayload.name); }); 

我不知道是否总是使用相同的事件可能会导致任何问题,可能是某种规模的碰撞,但这符合我的目的。

我发现的所有方法(包括socket.io-wildcard和socketio-wildcard)都不适用于我。 显然没有$发射在socket.io 1.3.5 …

读完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 }; 

这可能也是其他人的解决scheme。 然而,ATM我不完全明白为什么没有人似乎有问题与现有的“解决scheme”? 有任何想法吗? 也许这是我的旧节点版本(0.10.31)…

@Matthias Hopf答案

更新了v1.3.5的答案。 如果你想一起听老的事件和*事件,那么有一个错误。

 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 }; 

socket.io-client 1.7.3

截至2017年5月,无法使任何其他解决scheme的工作,我想如何 – 做了一个拦截器,使用Node.js仅用于testing目的:

 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) } }) 

参考文献: