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

JavascriptEventssocket.io

Javascript Problem Overview


Is it possible to have a socket.io client respond to all events without to have specify each event individually?

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

// 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.

Is this possible? How?

Javascript Solutions


Solution 1 - Javascript

Updated solution for 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.

NOTE: this only catches custom events, not connect/disconnect etc

Solution 2 - Javascript

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.

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

Solution 3 - Javascript

Finally, there is a module called socket.io-wildcard which allows using wildcards on client and server side

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

io.use(middleware);

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

io.listen(8000);

Solution 4 - Javascript

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

Solution 5 - Javascript

Note: this answer is only valid for socket.io 0.x

You can override 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));
});

Solution 6 - Javascript

As it is in v3.0 documentation:

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

Solution 7 - Javascript

The current (Apr 2013) GitHub doc on exposed events mentions 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.

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.

Solution 8 - Javascript

socket.io-client 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:

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:

Solution 9 - Javascript

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.

Solution 10 - Javascript

There is a long discussion about this topic going 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-wildcard that patches in a wildcard event onto Socket.IO (works with the current Socket.IO, ~0.9.14).

Solution 11 - Javascript

Even though this is a old question, I have the same problem and solved using the native socket in Node.js, which has a event of .on('data'), fired everytime some data comes. So this is what I've done so far:

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

Solution 12 - Javascript

All methods I found (including socket.io-wildcard and socketio-wildcard) didn't work for me. Apparently there is no $emit in socket.io 1.3.5...

After reading socket.io code, I patched up the following which DID work:

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

This might be a solution for others as well. However, ATM I don't exactly understand why nobody else seems to have issues with the existing "solutions"?!? Any ideas? Maybe it's my old node version (0.10.31)...

Solution 13 - Javascript

@Matthias Hopf answer

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

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

Solution 14 - Javascript

I'm using Angular 6 and the npm package: ngx-socket-io

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

...

constructor(private socket: Socket) { }

...

After connect the socket, I use this code, this is handling all custom events...

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDerick BaileyView Question on Stackoverflow
Solution 1 - JavascriptFlionView Answer on Stackoverflow
Solution 2 - JavascriptlukifferView Answer on Stackoverflow
Solution 3 - JavascriptMarian KlühspiesView Answer on Stackoverflow
Solution 4 - JavascriptKaustubh KarkareView Answer on Stackoverflow
Solution 5 - Javascriptleszek.hanuszView Answer on Stackoverflow
Solution 6 - JavascriptCarlos OliveiraView Answer on Stackoverflow
Solution 7 - JavascriptDan DascalescuView Answer on Stackoverflow
Solution 8 - JavascriptFabiano SorianiView Answer on Stackoverflow
Solution 9 - JavascriptDanView Answer on Stackoverflow
Solution 10 - JavascriptsffcView Answer on Stackoverflow
Solution 11 - JavascriptMaelView Answer on Stackoverflow
Solution 12 - JavascriptMatthias HopfView Answer on Stackoverflow
Solution 13 - JavascriptMaros PixelView Answer on Stackoverflow
Solution 14 - JavascriptAlejandroView Answer on Stackoverflow