Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Add wildcard support for events #434

Closed
edmellum opened this Issue · 84 comments
@edmellum

It would be great if you could use a wildcard to capture all events. For example:

client.on("*", function(data) {

}
@joshrtay

agreed.

EventEmitter2

@DennisRas

+1
This would allow us to create filters and what not for all events.

@dvv
  • another dependency
  • must be reflected at client side (code?)
  • should catchall be called before particular event? or in the order of definition? clarification needed
  • only sync behavior -- wouldn't it be better to introduce custom async filters for events?
@pyrotechnick

+1

only sync behavior -- wouldn't it be better to introduce custom async filters for events?
@dvv

I'm quite interested in this idea.

@tj
tj commented

some of the EE2 choices are not what I would consider ideal but I +1 the general idea of this, even if only "*" is supported

@dvv
dvv commented

truly catchall: manager.on("event", function(client, event, data) {} -- will also allow to reduce number of closures

@mikeal

i don't remember any resistance to just adding a catchall listener, the only debate I remember was whether or not we use "*" or if we go with another method name like .addGlobalListener()

@hdf
hdf commented

+1
I too would need a way to intercept all events, and have the specific handler get a look at them, only once I'm done processing it. Mostly for logging purposes would this be needed. Socket.io logger currently only logs to the console, and in a very self righteous way.
dvv -s approach is really to my liking.
In fact maybe it would be a good idea to have us relay the event to any specific handler, and we just get all events, as described by dvv.

@DennisRas

Please get this issue in motion :)
Would love to see this feature implemented.

@einaros

Well, ok, I just added EE2 to a branch in my fork: einaros@2107ff0

The branch is at: https://github.com/einaros/socket.io/commits/ee2

Thoughts are most welcome.

@tj
tj commented

if EE2 gets rid of the weird method names and adds .on('*') I'd +1 that

@3rd-Eden

I'm a -1 on EE2

It adds more bloat to the code, we also need to support it on the client side. Which means we would have to ship a extra 11.8 KB library (minified ~3.5kb). But with the up coming mobile market I would like to save as much bytes as possible.

If this is really only about having a wildcard / catch all listeners.. Then this should be done by overriding the existing emit function that just does one extra call to a all listener. This would be like a 3 - 5 LOC change (excluding comments ;)). And should be hidden behind a preference lock as it influence performance. EventEmitting is a hot code path and should always be as optimal and fast as possible. Adding wildcards will degrade performance.

@tj
tj commented

catch-all is definitely the more important part, it's easy enough to switch on the event after that if necessary

@hdf
hdf commented

Don't really care about wildcard's, or EE2, but a way, to intercept all events is a must.

@pyrotechnick

if EE2 ... adds .on('*') I'd +1 that

TJ you crazy bro...

server.on('foo.*', function(value1, value2) {
  console.log(this.event, value1, value2);
});

That's from the README of EE2. Naturally, the "foo." is optional.

if EE2 gets rid of the weird method names

I agree.

@tj
tj commented

@pyrotechnick the EE2 .on('*') isnt a catch-all iirc

@pyrotechnick

* is not catch-all in the sense that it blindly catches all events but it does effectively catch all events since the pattern * matches all channels.

It's inefficient; but it does work as expected.

@pyrotechnick

I was mistaken. You're right...

{EventEmitter2} = require 'eventemitter2'

emitter = new EventEmitter2 wildcard: on

emitter.on '*', ->
  console.log @event, arguments...

emitter.emit 'foo'
emitter.emit 'foo.bar'
isabel:hydrogen pyrotechnick$ coffee test.coffee 
foo

I almost prefer this behaviour when it comes to wildcards though.

When I think about all of this wildcard/"namespaced" events stuff it kind of makes me sad; JavaScript already has a fantastic way to match patterns -- they live in // or are constructed with RegExp. Is this just too slow?

@jrperina

Can I +1 the importance of this again. I'd love to see this in an upcoming release.

@jrperina

That doesn't work because I still can't connect to the event. In my application the server doesn't know the name of the room from the client. So I want to be able to respond to all messages for any room and ideally find out the name of the room that the message was sent on.

@mycall

Add regular expression support for events.. this way, ranges of verbs and nouns can be caught.

@ivzhao

+1

@jcrugzz

+1

@dmail

I would be fond of a super global method wich handle everything

io.set('global_listener', function(namespace, event, args, emit){
// do something based on namespace event and arguments
// I can or not call emit() to call event listeners linked with that namespace and that event
});

io.set('global_authorization', function(namespace, handshakeData, callback){
// based on namespace and handshakeData accept or not the connection
});

@HenrikJoreteg

I needed an emitter that supported catch-alls a. la. socket.on("*"), worked on the client, and was still light weight. So I took @visionmedia's emitter from UI Kit and extended it a bit. Perhaps it would be a decent fit for this. So, for what it's worth. I'll just leave this here: https://github.com/HenrikJoreteg/wildemitter

@rauchg
Owner

@HenrikJoreteg
We might add '*' out of the box to https://github.com/component/emitter.
Also, that emitter is going to power next socket.io. It includes an off shortcut to removeListener which is nice :D

@HenrikJoreteg

oh, awesome!

@abrkn

+1

@sebicas

+1

@vizo

+1

@tomsawyer

+=1

@playerx

+1

@sreuter

+1

@geekrohit

Has anyone worked towards this yet ? Any kind of trail ?

@danpetrikin

I have a sort of solution that worked well enough for the purposes we needed it for, but its not a full blown wildcard solution... more like an implementation of '*'

https://github.com/Attorney-Fee/socket.io

@omeid

+1

@riyuk

+1

@DanH42

I hate to leave a comment that doesn't contribute anything meaningful, but this has been requested for 2 years now, and everything constructive has already been said. So...

+1

@rauchg
Owner

This would be fairly easy to add in userland, I don't see the need of having it in the core codebase. If I can help with any hooks to make it easier to extend the event emitter functionality without too much monkey patching I'll gladly do so.

@rauchg rauchg closed this
@DanH42

How would this be implemented in userland? All the solutions I've seen involve forking the codebase, and some folks have linked to different libraries altogether.

In my case I only need a plain and simple "catch absolutely everything in one function," but RegEx support doesn't seem (to a guy who hasn't looked at the source too closely) too difficult, and would certainly be incredibly useful. I use regular expressions in my Express.JS routes all the time; it would be nice to be able to do the same in socket.io.

@rauchg
Owner

The transport layer / protocol would stay unaltered. You would simply override 'emit' on both ends to not simply do a map lookup but a more comprehensive (regexp based) search.

Quick implementation suggestions:

  • Override on to maintain a special datastructure for the regular expressions when '*' is found in the event name
  • Override emit to first do the fast case (regular map lookup), then go through the '*' listeners and see if they match.
@rauchg
Owner

Obviously this doesn't require a fork. What I meant by hooks is that we can potentially find a solution to not require the monkey-patching, but considering those 2 are pretty simple methods I don't consider that a big problem.

@lmjabreu

Just out of curiosity, couldn't we just override the socket.Manager.prototype.onClientMessage from userland?

I did so and worked just fine, in node, no changes to socket.io module. Not very pretty and likely to break but at least you avoid forking.

https://gist.github.com/lmjabreu/5714985

@SpencerC

Couldn't one simply add process.EventEmitter = require('eventemitter2').EventEmitter2 somewhere before socket.io is required? This seems to work for me...

@djrenren

Opening up the prototype is definitely not a userland fix. I understand not wanting to implement full regex support or anything but a simple socket.on('*') would go a long way.

@carpii

This ticket is 2 years old now.

Are there any plans to address it, as its clearly a useful feature?

If the answer is no, I would like to fork and add it myself.
But I would prefer to do this only if its likely to get merged back upsteam.

Can any devs answer this please?

@brunoduran

Agreed with almost all comments, fancy stuff can be more o less debatable, but a catch-all would be nice. Users can do it themselves, but a predefined procedure would be cleaner.

@chevex

It's a shame this doesn't exist.

@carpii

It does exist, see the link someone posted earlier
http://stackoverflow.com/questions/8832414/overriding-socket-ios-emit-and-on/8838225

Im using this, and it works great :)

@fjorgemota

+1

Do monkey patching to something simple like that seems, to me, something like a bad practice, however, I think that no big implementation should be used, something simple like Backbone.Events will be sufficient for most devs in this issue, I think. (although Backbone does not use "*", but "all" for the global event, passing in the event name that is originally called, which is just the best thing to do). (its just a suggestion, however) =)

@vicary

Personally +1 to the RegExp way, it feels more Javascript and less console when compared with the "*" wildcard.

But like the latest voices, a catch-all function seems more suitable.

Not sure if this is actually a socket.io issue tho.

A frozen API to blame IMO.

@geoah

In case anyone reads this thread and is still looking for a way to use wildcard events on 0.9.x and 1.0.0: https://www.npmjs.org/package/socketio-wildcard

@rauchg
Owner

Wonderful @geoah !

@geoah

@guille hehe, it ain't mine I just stumbled upon it. thanks for all you hard work btw ^_^

@NathanGRomano

Whipped up a middleware for socket.io last night.

https://www.npmjs.org/package/socket.io-events

@nathancharles

+1
It would be nice to cut the overhead of creating new listeners when the data will always be handled the same.
@geoah Thanks for the middleware, did exactly what I needed!

@omeid

If the middleware works fine, then socket.io should stay as is.

@chevex

This is one of those things that I personally feel makes perfect sense as part of socket.io itself. I see no argument for leaving it out except "that's not the way things are done around here", which is never a very good argument.

@rauchg
Owner

The argument is that we try to work just like the node EventEmitter, and node doesn't have this, so it would become a "socket.io-ism". There were extensive discussions in Node about adding it and it didn't make it through.

@DanH42

@chevex While this was originally my feeling as well, the new middleware support makes it pretty easy to add in yourself. Looking at socketio-wildcard as an example, it's dead simple to import and use; it'll probably just end up being like express.js where there's a couple pieces of middleware I almost always include.

@chevex

Those are much better arguments. I guess you wouldn't want the EventEmitter to behave differently from node's by default. And @DanH42 I also suppose you're right that augmenting it with middleware makes more sense for those who need it. I retract my statement :)

If only node's EventEmitter supported wildcards out of the box.

@rauchg
Owner

:+1:

@geoah geoah referenced this issue in lmjabreu/socket.io-wildcard
Open

Socket.io 1.0 support? #5

@peteruithoven

I see I missed this issues, I started a new issue on forwarding events:
#1715
It includes two ways to handle all events from socket.io 1.0 without altering it's source.

@RustyToms

I just want this for debugging. I don't have the authoritah to add or modify libraries in our project. :sob:

@francoismassart

+1
Sometimes, you need to know all the events that are propagating!

@betlab

+1

@MaffooBristol

I ended up using hden's socketio-wildcard module; it seems the most transparent method (by using middleware) and works quite nicely for me. But :+1: for getting this into core!

@NathanGRomano
@xenyou

+1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.