2012-05-01 84 views
60

有没有可能有一个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? 
}); 

我想这个回调函数,当任何/所有事情都是由客户端收到的插座被调用。 io代码。

这可能吗?怎么样?

+0

我打开在转发所有事件类型时遇到以下问题,我还添加了我找到的解决方案: https://github.com/Automattic/socket.io/issues/1715 –

回答

19

它看起来像socket.io库将它们存储在字典中。因此,如果不修改源代码,不要以为这是可能的。

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

也发现这个:http:// stackoverflow。com/questions/8832414/overriding-socket-ios-emit-and-on/8838225 –

10

在这里你去...

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太多,所以要小心。

+0

Socket.IO.js build:0.9.10,development。 –

+3

这是否最终在发布? – hacklikecrack

7

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

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

3

在Socket.IO存储库问题页面上有a long discussion about this topic。在那里发布了各种解决方案(例如,用EventEmitter2覆盖EventEmitter)。 lmjabreu几个星期前发布了另一个解决方案:一个名为socket.io-wildcard的npm模块,它将通配符事件补丁到Socket.IO(适用于当前的Socket.IO,〜0.9.14)。

+3

但这只是serverside ...他的模块在客户端(浏览器)上不可用 – Sander

9

注:这个答案是仅适用于socket.io 0.X

您可以覆盖插座$发出

用下面的代码,你有两个新的功能:

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

在调用apply之前,有关aync操作的任何建议。 \t的setTimeout(函数(){ \t \t \t \t original_ $ emit.apply(插座,[ '*'] CONCAT(参数));! \t \t \t \t如果(original_ $ emit.apply(插座,参数) ){ \t \t \t \t \t original_ $ emit.apply)(插座,[ '缺省']的concat(参数); \t \t \t \t} \t \t \t},2000); – Enki

+0

我正在使用Socket.IO 1.3.6,并且''socket'中似乎没有$ emit方法 – raimohanska

+0

确实。检查@Flion的答案为1.x版本 –

1

所有的方法,我发现(包括socket.io通配符和socketio通配符)我没有工作。显然在socket.io 1.3.5中没有$ emit ...

在读取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 
}; 

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

+0

我可以证实它的工作原理,正如你所观察到的,它是唯一可行的(从某种意义上说:对我而言)。非常感谢你! – mark

3

因为你的问题在寻求解决方案时相当普遍,我会介绍这个不需要破解代码的问题,只需改变你的使用方式插座。

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

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

和服务器的东西像...

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

如果总是使用相同的事件可能导致的任何问题,也许某种大规模的冲突,我不知道,但是这服务我的目的就好了。

1

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

为socket.io客户端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 
}; 

使用这样的更新的解决方案:

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

的答案都不为我工作,但的一个Mathias Hopf和Maros Pixel接近,这是我调整后的版本。

注:这仅捕获自定义事件,而不是连接/断开等

+2

谢谢,这帮助我调试丢失的事件! – Maitreya

+2

这工作完美 - 谢谢! – Jonathan

+1

不幸的是,没有使用'user。*'之类的东西。也许我可以设法实现它。 – C4u

12

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

完美运作 – tinybyte

2

通配符socket.io-client 1.7.3

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

参考文献:

相关问题