Socket.io Client: Mit einem Handler auf alle Ereignisse reagieren?

82

Ist es möglich, dass ein socket.io-Client auf alle Ereignisse reagiert, ohne jedes Ereignis einzeln angeben zu müssen?

Zum Beispiel so etwas (was momentan offensichtlich nicht funktioniert):

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

Ich möchte, dass diese Rückruffunktion aufgerufen wird, wenn alle Ereignisse vom clientseitigen socket.io-Code empfangen werden.

Ist das möglich? Wie?

Derick Bailey
quelle
Ich habe die folgende Ausgabe zum Weiterleiten aller Ereignistypen geöffnet und die gefundenen Lösungen hinzugefügt: github.com/Automattic/socket.io/issues/1715
Peter Uithoven

Antworten:

25

Es sieht so aus, als ob die Bibliothek socket.io diese in einem Wörterbuch speichert. Denken Sie daher nicht, dass dies möglich wäre, ohne die Quelle zu ändern.

Aus der Quelle :

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;
  };
lukiffer
quelle
3
fand auch dies: stackoverflow.com/questions/8832414/…
Derick Bailey
2019 glaube ich nicht mehr, dass dies der Fall ist.
Urasquirrel
82

Aktualisierte Lösung für 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
};

Verwenden Sie wie folgt:

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

Keine der Antworten hat bei mir funktioniert, obwohl die von Mathias Hopf und Maros Pixel nahe kam, ist dies meine angepasste Version.

HINWEIS: Dies fängt nur benutzerdefinierte Ereignisse ab, nicht das Verbinden / Trennen usw.

Flion
quelle
2
Vielen Dank, dies hat mir geholfen, fehlende Ereignisse zu debuggen!
Maitreya
1
Leider funktioniert es nicht mit Dingen wie 'user. *';. Vielleicht kann ich es schaffen, es umzusetzen.
C4d
Hallo, sehr gut, aber es könnte hilfreich sein, wenn Sie einige Ausgabebeispiele haben könnten ^^ Ich glaube, ich muss den Code ausführen, um Ihre Antwort zu verstehen :)
538ROMEO
24

Schließlich gibt es ein Modul namens socket.io-wildcard , mit dem Platzhalter auf Client- und Serverseite verwendet werden können

var io         = require('socket.io')();
var middleware = require('socketio-wildcard')();

io.use(middleware);

io.on('connection', function(socket) {
  socket.on('*', function(){ /* … */ });
});

io.listen(8000);
Marian Klühspies
quelle
11

Bitte schön ...

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

Dies wird fangen Veranstaltungen wie connecting, connect, disconnect, reconnectingzu, so tun kümmern.

Kaustubh Karkare
quelle
Socket.IO.js Build: 0.9.10, Entwicklung.
Kaustubh Karkare
3
Hat dies zu einer Veröffentlichung geführt?
Hacklikecrack
9

Hinweis: Diese Antwort gilt nur für socket.io 0.x.

Sie können Socket überschreiben . $ Emit

Mit dem folgenden Code haben Sie zwei neue Funktionen:

  • Fange alle Ereignisse ein
  • Nur Ereignisse abfangen, die von der alten Methode nicht abgefangen werden (dies ist ein Standard-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));
});
leszek.hanusz
quelle
Es gelten alle Hinweise zu einem Aync-Vorgang vor dem Aufruf. setTimeout (function () {original_ $ emit.apply (Socket, ['*']. concat (args)); if (! original_ $ emit.apply (Socket, Argumente)) {original_ $ emit.apply (Socket, [ 'default']. concat (args));}}, 2000);
Enki
Ich benutze Socket.IO 1.3.6 und es scheint keine $ socket
emit-
Tatsächlich. Überprüfen Sie @Flion Antwort für 1.x Versionen
leszek.hanusz
7

Das aktuelle GitHub-Dokument (April 2013) zu exponierten Ereignissen erwähnt asocket.on('anything') . Es scheint, dass 'irgendetwas' ein Platzhalter für einen benutzerdefinierten Ereignisnamen ist, kein tatsächliches Schlüsselwort, das ein Ereignis abfangen würde.

Ich habe gerade angefangen, mit Web-Sockets und Node.JS zu arbeiten, und musste sofort jedes Ereignis behandeln und herausfinden, welche Ereignisse gesendet wurden. Ich kann nicht glauben, dass diese Funktionalität in socket.io fehlt.

Dan Dascalescu
quelle
5

socket.io-client 1.7.3

Ab Mai 2017 konnte keine der anderen Lösungen so funktionieren, wie ich es wollte - einen Interceptor erstellt, der bei Node.js nur zu Testzwecken verwendet wurde:

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

Verweise:

Fabiano Soriani
quelle
3

Es gibt eine lange Diskussion zu diesem Thema auf der Socket.IO-Repository-Problemseite. Dort werden verschiedene Lösungen veröffentlicht (z. B. Überschreiben von EventEmitter mit EventEmitter2). lmjabreu hat vor ein paar Wochen eine andere Lösung veröffentlicht: ein npm-Modul namens socket.io-wildcard , das ein Wildcard-Ereignis auf Socket.IO patcht (funktioniert mit dem aktuellen Socket.IO, ~ 0.9.14).

sffc
quelle
4
Aber das ist nur serverseitig ... sein Modul kann nicht clientseitig verwendet werden (Browser)
Sander
3

Da Ihre Frage bei der Frage nach einer Lösung ziemlich allgemein war, werde ich diese Frage stellen, bei der der Code nicht gehackt werden muss, sondern lediglich die Verwendung des Sockets geändert wird.

Ich habe gerade beschlossen, dass meine Client-App genau dasselbe Ereignis sendet, jedoch mit einer anderen Nutzlast.

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

Und auf dem Server so etwas wie ...

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

Ich weiß nicht, ob die Verwendung des gleichen Ereignisses zu Problemen führen kann, möglicherweise zu Kollisionen in größerem Maßstab, aber dies diente meinen Zwecken in Ordnung.

Dan
quelle
1

Alle Methoden, die ich gefunden habe (einschließlich socket.io-wildcard und socketio-wildcard), haben bei mir nicht funktioniert. Anscheinend gibt es kein $ emit in socket.io 1.3.5 ...

Nachdem ich den Code von socket.io gelesen hatte, habe ich Folgendes gepatcht, was funktioniert hat:

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

Dies könnte auch eine Lösung für andere sein. Allerdings verstehe ich Geldautomaten nicht genau, warum sonst niemand Probleme mit den vorhandenen "Lösungen" zu haben scheint?!? Irgendwelche Ideen? Vielleicht ist es meine alte Knotenversion (0.10.31) ...

Matthias Hopf
quelle
Ich kann bestätigen, dass es funktioniert und, wie Sie bemerkt haben, das einzige ist, das funktioniert (im Sinne: auch für mich). Vielen Dank!
Markieren Sie
1

@ Matthias Hopf Antwort

Aktualisierte Antwort für v1.3.5. Es gab einen Fehler mit Argumenten, wenn Sie alte Ereignisse und *Ereignisse gemeinsam anhören möchten .

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
};
Maros Pixel
quelle
1

Obwohl dies eine alte Frage ist, habe ich das gleiche Problem und habe es mit dem nativen Socket in gelöst, der Node.jsdas Ereignis .on ('data') enthält und jedes Mal ausgelöst wird, wenn einige Daten eingehen. Das habe ich bisher gemacht:

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

Ich verwende Angular 6 und das npm-Paket: ngx-socket-io

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

...

constructor(private socket: Socket) { }

...

Nach dem Anschließen des Sockets verwende ich diesen Code, der alle benutzerdefinierten Ereignisse behandelt ...

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