Socket.ioクライアント:1つのハンドラーですべてのイベントに応答しますか?


83

各イベントを個別に指定せずに、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コードがすべてのイベントを受信したときに、このコールバック関数を呼び出す必要があります。

これは可能ですか?どうやって?


すべてのイベントタイプの転送について次の問題を開きました。また、見つけたソリューションを追加しています:github.com/Automattic/socket.io/issues/1715
Peter Uithoven 2014

回答:


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

3
また、これを見つけました:stackoverflow.com/questions/8832414/…–
Derick Bailey

2019年には、これはもう当てはまらないと思います。
Urasquirrel

82

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

MathiasHopfとMarosPixelのいずれかが近づいてきましたが、これは私の調整済みバージョンです。

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


2
ありがとう、これは私が行方不明のイベントをデバッグするのを助けました!
マイトレーヤ2016年

1
残念ながら、「user。*」のようなものでは動作しません。多分私はそれを実装することができます。
c4d 2017年

こんにちは、とても良いですが、いくつかの出力例があれば役立つかもしれません^^あなたの答えを理解するためにコードを実行する必要があるように感じます:)
grobouDu 0619年

24

最後に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);

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あまりにも、その世話を行うことを。


Socket.IO.jsビルド:0.9.10、開発。
Kaustubh Karkare 2012年

3
これはリリースになりましたか?
hacklikecrack 2013年

9

注:この回答はsocket.io0.xでのみ有効です。

ソケットをオーバーライドできます。$ 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));
});

適用を呼び出す前のaync操作に関するアドバイス。setTimeout(function(){original_ $ emit.apply(socket、['*']。concat(args)); if(!original_ $ Emit.apply(socket、arguments)){original_ $ emit.apply(socket、[ 'default']。concat(args));}}、2000);
エンキ2014年

私はSocket.IO1.3.6を使用していますが、$ emitメソッドはsocketもう存在しないようです
raimohanska 2015

確かに。@Flionの回答で1.xバージョンを確認してください
leszek.hanusz 2016

7

公開されたイベントに関する現在(2013年4月)のGitHubドキュメントには、が記載されていsocket.on('anything')ます。'anything'はカスタムイベント名のプレースホルダーであり、イベントをキャッチする実際のキーワードではないようです。

WebソケットとNode.JSの操作を開始したばかりで、すぐにイベントを処理し、送信されたイベントを見つける必要がありました。この機能がsocket.ioにないことは信じられません。


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

参照:


3

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


4
しかし、それはサーバーサイドだけです...彼のモジュールはクライアントサイド(ブラウザ)では使用できません
Sander

3

あなたの質問は解決策を求めるのにかなり一般的だったので、コードをハッキングする必要がなく、ソケットの使用方法を変更するだけで、これを提案します。

クライアントアプリにまったく同じイベントを送信させることにしましたが、ペイロードは異なります。

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

そしてサーバー上では、次のようなものがあります...

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

常に同じイベントを使用すると問題が発生する可能性があるかどうかはわかりませんが、大規模な衝突が発生する可能性がありますが、これは私の目的には十分に役立ちました。


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

1

私が見つけたすべてのメソッド(socket.io-wildcardとsocketio-wildcardを含む)は私には機能しませんでした。どうやらsocket.io1.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)です...


私はそれが機能することを確認できます、そしてあなたが観察したように、機能するのは唯一のものです(ある意味で:私にとっても)。どうもありがとうございました!
マーク

1

@MatthiasHopfの回答

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

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.