Namespaced EventEmitters?

475 views
Skip to first unread message

Marak Squires

unread,
May 30, 2011, 12:18:50 AM5/30/11
to nodejs
Has anyone written any libraries in userland that can do namespaced events? Something like http://docs.jquery.com/Namespaced_Events ?



Jacob Chapel

unread,
May 30, 2011, 1:56:05 AM5/30/11
to nod...@googlegroups.com

This would be awesome. I saw h1jinx talking about patching it in to ee.

On May 29, 2011 9:18 PM, "Marak Squires" <marak....@gmail.com> wrote:
> Has anyone written any libraries in userland that can do namespaced events?
> Something like http://docs.jquery.com/Namespaced_Events ?
>
> --
> You received this message because you are subscribed to the Google Groups "nodejs" group.
> To post to this group, send email to nod...@googlegroups.com.
> To unsubscribe from this group, send email to nodejs+un...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/nodejs?hl=en.
>

Elijah Insua

unread,
May 30, 2011, 2:09:31 AM5/30/11
to nod...@googlegroups.com
namespacing events is slow.  it means that on every event emission, we have to churn through a list and do a compare.

As this is how node does basically everything (net, fs, proces, etc)  it would add a huge overhead.

I say do it in userland, because you'll see less performance degradation. 

-- Elijah

Marak Squires

unread,
May 30, 2011, 2:10:34 AM5/30/11
to nod...@googlegroups.com
I agree it belongs in userland. Was just wondering if anyone was dealing with this already. h1jinx seems to be on to something with EventVat

Matt

unread,
May 30, 2011, 6:56:11 AM5/30/11
to nod...@googlegroups.com
On Mon, May 30, 2011 at 2:09 AM, Elijah Insua <tmp...@gmail.com> wrote:
namespacing events is slow.  it means that on every event emission, we have to churn through a list and do a compare.

Only if your implementation is dumb. Seems like it would be trivial to split the event name on "." and do a two-level hash/object.

(would still be slower of course, but not *that* much slower).

Matt.

Matthew Richmond

unread,
May 30, 2011, 7:53:31 AM5/30/11
to nod...@googlegroups.com, Me
Also, you could attach the listeners to an object and then it could be accessed as Object[namespace][event] same O as variable assignment/dereference.

--

Kris Walker

unread,
May 30, 2011, 10:13:18 AM5/30/11
to nodejs
I took a crack at namespaced events back in January and used in a
couple of projects. Since then I've ported it to CoffeeScript and used
it on both the client side and in Node.js.

There was something else I needed in an event emitter which I wasn't
finding anywhere else: I wanted to attach a handler after an event had
already been triggered and have the handler be invoked as soon as it
was attached. I call it "stateful" events.

Anyway, this is the latest implementation I've been using

https://gist.github.com/998935

and the older one from a few months ago

https://github.com/kixxauth/js_future/tree/master/lib/emitters

dhruvbird

unread,
May 31, 2011, 12:03:31 AM5/31/11
to nodejs
Hello,

I quite like the idea in principle, but I've never ever used
namespaces in jQuery's trigger/bind (and I've used them quite a bit).
Neither have I felt then need when doing node.js programming. This
makes me wonder what real use cases exist for such a thing. Another
thing to consider (maybe) would be whether it woul break existing code
that uses dot as a separator.


Regards,
-Dhruv.

Marcel Laverdet

unread,
May 31, 2011, 2:42:18 AM5/31/11
to nod...@googlegroups.com
I'm just thinking aloud here.. but does anyone else think that the EventEmitter class is maybe too high level for core Node? What I like about Node is that the core functionality is super simple; just the bare minimum to get a job done. Chances are you will want to build a layer in between yourself and core Node before you start building large products.

You could either want namespaced events (jQuery), multiple listeners (DOM level 2), single listener (DOM level 0), prioritized listeners (?), or maybe another pattern. The fact that Node chose the EventEmitter paradigm seems rather arbitrary.

What if instead of:
process.stdin.on('data', function() {
});

It was just:
process.stdin.ondata = function() {
};

If you wanted an emitter you would have to do:
var emitter = new EventEmitter(process.stdin, 'ondata');
emitter.on(function() {
});

Am I crazy here? I picked the stream example because intuitively it doesn't make sense that streams should have multiple listeners in the first place.

mscdex

unread,
May 31, 2011, 3:05:53 AM5/31/11
to nodejs
On May 31, 2:42 am, Marcel Laverdet <mar...@laverdet.com> wrote:
> Am I crazy here? I picked the stream example because intuitively it doesn't
> make sense that streams should have multiple listeners in the first place.

I think there is a case to be made for the usefulness of multiple
listeners (including use with streams). An example might be you have
an automatic backup mechanism for incoming file streams (http or
otherwise) where you have one copy be saved locally to disk and
another copy be sent to s3 or somewhere else.

Mikeal Rogers

unread,
May 31, 2011, 1:00:53 PM5/31/11
to nod...@googlegroups.com
you might have a good case about EventEmitters being used by third parties and that they are too high level for core, but most of the core APIs use EventEmitter so it's gotta be in there for them to use.

i think the current implementation is the bare minimum, which is good for core.

hij1nx.dev

unread,
May 31, 2011, 1:28:50 PM5/31/11
to nod...@googlegroups.com
+1 for sparse core. however, my 2 cents... a lot of day to day programming in node I find is associated with eventEmitters. If there are good use cases, performance is on parity, and the additional code is nominal, it seems reasonable to add namespaces and wildcards. That said, there seems to be many levels of usage for eventEmitters, the higher the level the less frequent the usage.

1) One to one relationships of events to listeners.
2) One to many relationships of events to listeners.
3) Many to many relationships of events to listeners.
4) Many to many relationships of events to listeners where an emission may conditionally cast a wide net.
5) Many to many relationships of events to listeners where a listener may conditionally cast a wide net.

Here's what i mean...

    var tests = {
      'foo/*': 4, // should fire 4 times.
      'foo/*/bar': 2,  // should fire 2 times.
      'foo/*/*': 3,  // should fire 3 times.
      'foo/bar/bar': 2  // should fire 2 times.
    }
    
    Object.keys(tests).forEach(function (event) {
      var vat = new EventEmitter2(),
          count = 0;
    
      vat.on(event, function () {
        eyes.inspect(arguments, event);
        count++;
      });
    
      eyes.inspect(event, 'Beginning test for');
    
      vat.emit('foo/box/bar', 1, 2, 3, 4);
      vat.emit('foo/bar/*', 5, 6, 7, 8);
      vat.emit('foo/*/*', 9, 10, 11, 12);
      vat.emit('foo/*');
    
      assert.equal(count, tests[event]);
    });

I've been experimenting with the idea here: https://github.com/hij1nx/EventEmitter2

-- 
hij1nx
http://twitter.com/hij1nx

On Tuesday, May 31, 2011 at 1:00 PM, Mikeal Rogers wrote:

you might have a good case about EventEmitters being used by third parties and that they are too high level for core, but most of the core APIs use EventEmitter so it's gotta be in there for them to use.

i think the current implementation is the bare minimum, which is good for core.

--

dhruvbird

unread,
May 31, 2011, 4:48:33 PM5/31/11
to nodejs
Hello Marcel,

I think you make a good point. Maybe EventEmitter was just something
that "fit-in" when the original developers make the API. Plus, it's a
very jQuery-ish thing - seems to have been directly borrowed from
trigger/bind.

However, I agree with you on the observation that other higher level
constructs such as:
1. EventPipe (mentioned on some other thread),
2. EventQueue (queues up events in case of no listener) and
3. PriorityEvent (maybe for weighted load balancing?)

should all be provided (maybe??) as a special event-processing-
library. Additionally, it would be great if they were all composable
so that users can combine them in some meaningful way - something like
Raid-10 which is raid 1 on raid 0.

Regards,
-Dhruv.

On May 31, 11:42 am, Marcel Laverdet <mar...@laverdet.com> wrote:
> I'm just thinking aloud here.. but does anyone else think that the
> EventEmitter class is maybe too high level for core Node? What I like about
> Node is that the core functionality is super simple; just the bare minimum
> to get a job done. Chances are you will want to build a layer in between
> yourself and core Node before you start building large products.
>
> You could either want namespaced events (jQuery), multiple listeners (DOM
> level 2), single listener (DOM level 0), prioritized listeners (?), or maybe
> another pattern. The fact that Node chose the EventEmitter paradigm seems
> rather arbitrary.
>
> What if instead of:
> process.stdin.on('data', function() {
>
> });
>
> It was just:
> process.stdin.ondata = function() {
>
> };
>
> If you wanted an emitter you would have to do:
> var emitter = new EventEmitter(process.stdin, 'ondata');
> emitter.on(function() {
>
> });
>
> Am I crazy here? I picked the stream example because intuitively it doesn't
> make sense that streams should have multiple listeners in the first place.
>

Ramki Gaddipati

unread,
May 31, 2011, 10:08:36 PM5/31/11
to nodejs
The jQuery style of namespacing of events seem to be overloaded on
what `namespacing` means.
It could be used to group events by the class of listeners as well as
nature of the event being triggered. That is, namespaces can be
created by both listeners and emitters and all such namespaces get
identical treatment in triggering and unbind functions.

The problem namespacing of events by emitter solves (reducing the
noise for the listener) and the one solved by grouping of listeners
(convenience in unbind phase) are mutually exclusive.

I think, such grouping of two exclusive sets into one leads to
confusion.
If one reads a piece of code like
searchService.on('searchResult.imageViewer.image', function()
{...});
she cannot determine which part of the namespace qualifies the nature
of the event and which part qualifies the listener, unless she goes
through code of all the emitters or listeners.
Rewriting the above line as follows
searchService.on('searchResult.image', function(){...}),
'ImageViewer');
makes it clear, that the searchResult.image is the specialization
searchResult event being emitted and isolates concern of grouping
listeners.

The "." in a namespace is used to indicate a specialization/nesting in
conventional namespace declarations. However, it is also overloaded to
indicate a tagging like behavior as in the case of CSS classes. It is
nearly equivalent of using same operator for both logical AND and OR.

If a decision to implement namespaces for events in Node is made, I
think, we should adopt the jQuery model of namespacing.

+ramki

hij1nx.dev

unread,
Jun 2, 2011, 12:55:06 PM6/2/11
to nod...@googlegroups.com
I've implemented a namespaced EventEmitter. 

It supports wildcards.
It enhances the "once" concept (the third parameter to the addListener method accepts a number to determine the number of times a listener should listen before being removed). 

On average, it appears to perform better than the existing Node.js EventEmitter (according to the benchmarks)
It works in the browser (ive tested with firefox, chrome and safari).
It's not too much bigger 5.7K (de-commented) VS. 4.1K (has no comments)


I'm not proposing this for core, i'm just hacking.
Reply all
Reply to author
Forward
0 new messages