Add wildcard support for events #434

Closed
edmellum opened this Issue Jul 29, 2011 · 120 comments

Projects

None yet
@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 Oct 3, 2011

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 Oct 4, 2011

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 Oct 9, 2011

+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 Oct 9, 2011

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 Oct 9, 2011

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

@hdf
hdf commented Oct 9, 2011

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 Oct 9, 2011

@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

@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

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 May 20, 2013
@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

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

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.

@internalfx

👍

@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

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

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

👍

@geoah geoah referenced this issue in lmjabreu/socket.io-wildcard Jul 10, 2014
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. 😭

@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 👍 for getting this into core!

@NathanGRomano
@xenyou

+1

@vsdigitall

++++++

@EddieOne

+1 would be useful for debugging.

@johnmanko

If it's a matter of someone just working on this, I'd like to give it a shot. I'll need some to learn the socket.io codebase, and I'll probably spend some time looking at other such implementations. What are your thoughts on regex patterns? Too slow? Of course, I'm not going to waste my time if it's not something that would be considered for a merge (I don't care if my implementation is rejected, but if there is no interest then why bother, right?). Will a maintainer please advise?

@NathanGRomano
@Tectract

+1 this issue is going on 5 years old. Why hasn't wildcard support been added in, again?

@DutchKev

+1

@jimutt

+1

@Darker

+666

@MaffooBristol

Guys, seriously. Everyone wants this feature- I think they get it. Let's all stop with the plus-ones, please? I'd rather get an update email when there's some actual progress with the issue.

@rauchg
@carpii

A voting system would be great, but doesnt seem likely to happen anytime soon.

I guess the problem is a solution has been posted many times now, but scrolls out of view because of all the +1 comments.

The socketio-wildcard module has been working well for me (admittedly I haven't updated to latest node yet).
It would be useful if someone could explain why this lib is not suitable?

@MaffooBristol

Yeah, socketio-wildcard works perfectly well, but it's still an extra dependency that is so simple that it would be nice to be introduced into core and just end this whole issue thread once and for all. Also it removes any room for confusion as to which is the best external module to use (often similarly named). Also agree that it would be good if GitHub had a voting system, if only there was a way we could vote on it...!

@n2liquid

I may be dumb, but I have no clue how to set up socketio-wildcard with IO client objects. This should seriously, seriously be included in the core. If socket.io's maintainers don't want to do it, someone should just fork this project and we could all move there, because this is just ridiculous and I have honestly have zero trust in socket.io now.

I understand that maintainers don't have to accept every proposal, but this? This just totally baffles me. Way to go.

@rauchg

@n2liquid it's not as clear that this should be in core, but the discussion is welcome. For example, no other Node event emitter behaves this way, even though a discussion was had there as well when.

@carpii

@rauchg

it's not as clear that this should be in core, but the discussion is welcome

Could we have a discussion about this then?

I can understand your point that this sort of emitter is not necessarily common in the node world, but it depends what you are trying to achieve....
Is the idea to strictly adhere to conventions, or provide a really useful library?

It seems clear that many users of socket.io are really stumbling without this feature being in core, and it seems reasonable for a user to expect that it should be.

Or to put it another way, what are the arguments to NOT provide this feature in socket.io?

Even if the implementation is not 'textbook correct', it would result in a standard way to implement these 'catchall' handlers in socket.io, rather than people having to resort to lots of different libraries and methods.
Directing people to a third party lib or workaround only fragments things, and makes it even more fragile trying to maintain a codebase which uses socket.io

I would much rather there was a formal way to handle catchall packets, and then if it needs to be changed later, at least there can be a recommended migration procedure, rather than just leaving it for the user to find their own route through the wilderness

@Michael77

@rauchg I think a cool way to implement this would to have a socket.use(function(data,next){..}) function that catches all events on the socket, and is passed a next() function that passes control from the catchall to subsequent catchalls or default event handlers.

This is how I am using socket.io right now because I needed a way to limit the amount of events coming in per/minute, which I believe is a common use case. Thanks for reading my 2 cents.

@n2liquid

I like @Michael77's solution the most. It doesn't touch the event emitter interfaces or implementation and even allows for more things than we're asking here (e.g. @Michael77's message throttling implementation and who knows what else).

I know there's a middleware / use function in socket.io, but it's not usable on the client library, and I'm not sure if it serves this same purpose.

@rauchg

@carpii there are always great reasons to not support something: adding complexity, reducing familiarity. This feature checks off both.

I like the socket.use idea a lot, on top of which one could easily implement the wildcard extension on the client.

@rauchg

Thanks @carpii @Michael77 @n2liquid for your feedback on this btw.

@n2liquid

@rauchg, I'm sorry I said those bad things about socket.io. I was having a bad day. Thank you for this project; it may not be perfect (yet), but it sure is very useful.

Also: hden/socketio-wildcard#13

@rauchg

@n2liquid all feedback is welcome – thank you (and to @hden for that quick fix on socket.io-wildcard).

@akotlar

scoketio-wildcard seems like a perfectly valid solution. I found myself also wanting to get the event name in callback, so that I could wrap the socket listener and propagate events through the wrapper, rather than directly exposing the socket to the rest of my application. My understanding is that this would require Event Emitter 2 if I wanted to do this with a wildcard. Is this just something silly to do, better to directly expose the socket? Something based on listening for 'newListener' in the wrapper (but don't know how to trigger on socket event, only how to register the socket event based on the calling functions registering a new event in the wrapper)? Anyone else interested in being able to access the event name within the callback?

@hden

@akotlar The event name is available in the callback if you are using scoketio-wildcard.

@akotlar

Ah, thanks! It may be useful to specify this in the socket.io-wildcard readme.

@alexey-sh

how it's going?
+1 for on("*", function () { for both client and server

@emin93

+1 all the way

@hden

@alexey-sh @emin93 If you would kindly read the document from https://github.com/hden/socketio-wildcard, yes it's possible to do so for both client and server.

@emin93

@hden Thanks and yes i saw that and i'm already using it. But it's an extra dependency and nothing speaks against integrating it directly into Socket.IO core, that's why it gets a +1 from me.

@juodumas juodumas referenced this issue in feathersjs/feathers-socket-commons Apr 18, 2016
Closed

Support acknowledgement timeouts #9

@mkhahani

It can be handled in the app logic using one event name for all events:

socket.emit('public-event', {'type': 'login', ...});
socket.emit('public-event', {'type': 'logout', ...});
@juanpaulo

+1 even though issue is closed.

@crobinson42

+💯 bang!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment