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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10405070/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 01:11:02  来源:igfitidea点击:

Socket.io Client: respond to all events with one handler?

javascripteventssocket.io

提问by Derick Bailey

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?

这可能吗?如何?

采纳答案by lukiffer

It looks like the socket.io library stores these in a dictionary. As such, don't think this would be possible without modifying the source.

看起来 socket.io 库将这些存储在字典中。因此,不要认为不修改源就不可能做到这一点。

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

回答by Flion

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

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

回答by Marian Klühspies

Finally, there is a module called socket.io-wildcardwhich 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);

回答by Kaustubh Karkare

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, reconnectingtoo, so do take care.

这将赶上样事件connectingconnectdisconnectreconnecting太,所以做照顾。

回答by leszek.hanusz

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:

使用以下代码,您可以使用两个新函数:

  • Trap all events
  • Trap only events which are not trapped by the old method (it is a default listener)
  • 捕获所有事件
  • 仅捕获旧方法未捕获的事件(它是默认侦听器)
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));
});

回答by Dan Dascalescu

The current (Apr 2013) GitHub doc on exposed eventsmentions a socket.on('anything'). It appears that 'anything' is a placeholder for a custom event name, not an actual keyword that would catch any event.

当前(2013 年 4 月)关于公开事件的 GitHub 文档提到了socket.on('anything'). 似乎“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. Can't quite believe this functionality is missing from socket.io.

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

回答by Fabiano Soriani

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:

参考:

回答by sffc

There is a long discussion about this topicgoing on at the Socket.IO repository issue page. There are a variety of solutions posted there (e.g., overriding EventEmitter with EventEmitter2). lmjabreu released another solution a couple weeks ago: a npm module called socket.io-wildcardthat patches in a wildcard event onto Socket.IO (works with the current Socket.IO, ~0.9.14).

关于这个话题进行了长时间讨论在Socket.IO库发行回事。那里发布了各种解决方案(例如,用 EventEmitter2 覆盖 EventEmitter)。lmjabreu 几周前发布了另一个解决方案:一个名为socket.io-wildcard的 npm 模块,它将通配符事件修补到 Socket.IO(适用于当前的 Socket.IO,~0.9.14)。

回答by Dan

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.

我不知道总是使用相同的事件是否会导致任何问题,也许是某种规模的碰撞,但这很好地满足了我的目的。

回答by Maros Pixel

@Matthias Hopf answer

@Matthias Hopf 回答

Updated answer for v1.3.5. There was a bug with args, if you wanna listen on old event and *event together.

更新了 v1.3.5 的答案。如果您想一起收听旧事件和*事件,则 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
};