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)); });
这将捕获connecting
, connect
, disconnect
, reconnecting
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) } })
参考文献: