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

时间:2012-05-01 22:08:22

标签: javascript events 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代码接收到任何/所有事件时调用此回调函数。

这可能吗?怎么样?

14 个答案:

答案 0 :(得分:66)

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

像这样使用:

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

没有一个答案适合我,虽然Mathias Hopf和Maros Pixel的一个很接近,这是我调整后的版本。

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

答案 1 :(得分:23)

看起来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;
  };

答案 2 :(得分:18)

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

答案 3 :(得分:11)

你去......

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等事件,所以要小心。

答案 4 :(得分:9)

注意:此答案仅对socket.io 0.x

有效

您可以覆盖套接字。$ emit

使用以下代码,您有两个新功能:

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

答案 5 :(得分:7)

当前(2013年4月)GitHub doc on exposed events提及socket.on('anything')。 “任何事物”似乎是自定义事件名称的占位符,而不是捕获任何事件的实际关键字。

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

答案 6 :(得分:5)

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

参考文献:

答案 7 :(得分:3)

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

答案 8 :(得分:3)

因为你的问题在寻求解决方案时非常普遍,所以我推测这个问题不需要破解代码,只是改变你使用套接字的方式。

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

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

在服务器上,类似......

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

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

答案 9 :(得分:2)

即使这是一个老问题,我也遇到了同样的问题,并使用Node.js中的本机套接字解决了此问题,该套接字具有.on('data')事件,每次有数据传入时都会触发。所以这是我到目前为止所做的:

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

答案 10 :(得分:1)

我找到的所有方法(包括socket.io-wildcard和socketio-wildcard)都不适用于我。显然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)......

答案 11 :(得分:1)

@Matthias Hopf回答

更新了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
};

答案 12 :(得分:0)

我正在使用 Angular 6 和npm软件包: ngx-socket-io

import { Socket } from "ngx-socket-io";

...

constructor(private socket: Socket) { }

...

连接套接字后,我使用此代码,这将处理所有自定义事件...

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

答案 13 :(得分:0)

v3.0 documentation中一样:

socket.onAny((event, ...args) => {
  console.log(`got ${event}`);
});