87

各イベントを個別に指定せずに、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 コードで任意のイベントまたはすべてのイベントが受信されたときに、このコールバック関数が呼び出されるようにします。

これは可能ですか?どのように?

4

14 に答える 14

85

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 つが近づきましたが、これは私の調整バージョンです。

注:これはカスタムイベントのみをキャッチし、接続/切断などはキャッチしません

于 2015-11-27T14:58:03.520 に答える
25

最後に、クライアント側とサーバー側でワイルドカードを使用できる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);
于 2016-05-11T10:07:05.687 に答える
25

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;
  };
于 2012-05-01T22:18:14.123 に答える
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));
});

connectingこれは、connect、などのイベントもキャッチするので、注意してくださいdisconnectreconnecting

于 2012-10-14T17:41:08.443 に答える
9

注: この回答は、socket.io 0.x に対してのみ有効です。

socket.$emitをオーバーライドできます

次のコードには、次の 2 つの新しい関数があります。

  • すべてのイベントをトラップする
  • 古い方法ではトラップされないイベントのみをトラップします (デフォルトのリスナーです)。
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));
});
于 2013-10-01T16:10:12.073 に答える
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)
  }
})

参考文献:

于 2017-05-16T22:38:09.033 に答える
3

このトピックについては、Socket.IO リポジトリの問題ページで長い議論が行われています。そこにはさまざまなソリューションが投稿されています (たとえば、EventEmitter を EventEmitter2 でオーバーライドするなど)。lmjabreu は数週間前に別のソリューションをリリースしました:ワイルドカード イベントを Socket.IO にパッチするsocket.io-wildcardと呼ばれる npm モジュールです(現在の Socket.IO、~0.9.14 で動作します)。

于 2013-06-23T08:30:11.987 に答える
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)です...

于 2015-04-30T01:04:38.620 に答える