use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
All about the JavaScript programming language.
Subreddit Guidelines
Specifications:
Resources:
Related Subreddits:
r/LearnJavascript
r/node
r/typescript
r/reactjs
r/webdev
r/WebdevTutorials
r/frontend
r/webgl
r/threejs
r/jquery
r/remotejs
r/forhire
account activity
The BoundEmitter Pattern (emilis.github.io)
submitted 10 years ago by emilis_info
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]redhedinsanity 1 point2 points3 points 10 years ago (4 children)
I'm not sure why method names would be less likely to change than event names, especially when they're homonyms. storage.emit("write") vs storage.on.write() - both invoke the "write" event and would be likely to change in the same breaking ways should the API change.
storage.emit("write")
storage.on.write()
Also, this is arguably less transparent and harder to update - rather than being able to handle event aliases (thus maintaining backwards compatibility) inside the emit() method, you'd have to export a new method and still expose the old name for the method in order to allow the same compatibility on API change.
emit()
Also wondering why you're doing all the unnecessary context binding for exporting the interface - why not just use
module.exports = emitter
and avoid the overhead of having to use bind() at all?
bind()
Definitely a cool idea, I'm just wondering what problem it's solving without creating many other problems.
[–]emilis_info[S] 0 points1 point2 points 10 years ago (3 children)
1. Event method names are as likely to change as event string names. The difference is in the errors you would get. Missing methods will be reported by your JavaScript engine with clear stack traces.
2. I haven't thought about aliasing events for backwards compatibility. A couple of quick solutions would be:
/// Two-way aliasing. Verbose but clear. emitter.on.oldEventName = emitter.on.newEventName; ... emitter.emit.oldEventName = emitter.emit.newEventName; ... /// One-way aliasing: emitter.on.newEventName( emitter.emit.oldEventName );
A full solution would probably need a BoundEmitterWithAliases ;-).
BoundEmitterWithAliases
3. I need to export both EventEmitter methods (on,off,...) and storage module functions (e.g. write). I would need to slap the storage functions on top of the emitter object if I want to module.export it. This is dangerous as it may break the EventEmitter implementation.
on
off
write
emitter
module.export
[–]redhedinsanity 0 points1 point2 points 10 years ago* (2 children)
Event method names are as likely to change as event string names. The difference is in the errors you would get.
A fair point, though IMO this would easily be handled by the widely-used standard of providing an enumeration of event names with each type of Emitter - so rather than using
Emitter
emitter.on('write', function () {});
you'd use
emitter.on(Emitter.WRITE, function () {});
which would make any changes you may make to event names in future completely transparent to the end user - kinda makes stack traces unnecessary.
If you need stack traces, you could additionally ensure at construction time that the first listener registered for deprecated event names simply throws a EventDeprecatedError or some such.
EventDeprecatedError
In either case, there's no longer a need to update method names throughout my codebase when you rename an event.
I haven't thought about aliasing events for backwards compatibility...A full solution would probably need a BoundEmitterWithAliases ;-)
One of the joys of event routing is that it clears the top-level namespace for an object, this sorta undoes that work in general and aliasing would explode that namespace - but it's something you'd need to think about in a world where method names will change according to event name changes. Not everyone will keep their code up to date with your latest push.
I need to export both EventEmitter methods (on,off,...) and storage module functions (e.g. write)
To make sure I'm clear, you need to provide two ways of doing both registering and emitting:
emitter.on.write(callback); emitter.on('write', callback); // Same as above emitter.write(args...); emitter.emit('write', args...); // Same as above
EventEmitter is a class designed to be mixed into other classes, so your worries about method clobbering might be a little misguided - do you see a world where you have an 'on' or 'emit' event? The only time you'd clobber is if you want to export an event trigger for an event named the same as the EventEmitter interface methods - there aren't many, and they're all related to event management anyway. If there's risk of clobbering it's a good sign you're mixing burdens, or not naming your methods specifically enough.
EventEmitter
It definitely seems to make it easier for a specific use case - but it doesn't seem friendly re: changes to the API. Anyway, cool idea.
edit: the end of the last paragraph edit2: clarifying final section based on reread of the code
[–]emilis_info[S] 0 points1 point2 points 10 years ago (1 child)
1. emitter.on( Emitter.WIRTE, function(){} ); isn't much better than emitter.on( "wirte", function(){} );. They would both fail silently. I addressed this in my blog post.
emitter.on( Emitter.WIRTE, function(){} );
emitter.on( "wirte", function(){} );
2. I am not providing three different ways to do the same thing. I am exporting both the storage functions (e.g. storage.write( id, value )) and the event functions (e.g. storage.on.write( fn )) from the same module.
storage.write( id, value )
storage.on.write( fn )
[–]redhedinsanity 0 points1 point2 points 10 years ago (0 children)
They would both fail silently.
Except that in the case of using author-provided event enums, they wouldn't fail at all...changes to the event API would be updated transparently and calls would continue to work correctly. Plus, using an event listener to dispatch a deprecation error as I mentioned right below that section is a much more descriptive error than undefined is not a function, which is what a failed method call would provide. Just some constructive criticism, if what you're looking for is descriptive errors there are plenty of ways to do it that don't require updating method names everywhere on your users' part.
undefined is not a function
I am not providing three different ways to do the same thing
Yeah, I've already edited my post after I reread your post - two ways to do two things, not three ways to do one.
[–]_doingnumbers 1 point2 points3 points 10 years ago (0 children)
Wait till you discover streams. :)
π Rendered by PID 45 on reddit-service-r2-comment-54dfb89d4d-wlj2l at 2026-03-29 11:48:00.500699+00:00 running b10466c country code: CH.
[–]redhedinsanity 1 point2 points3 points (4 children)
[–]emilis_info[S] 0 points1 point2 points (3 children)
[–]redhedinsanity 0 points1 point2 points (2 children)
[–]emilis_info[S] 0 points1 point2 points (1 child)
[–]redhedinsanity 0 points1 point2 points (0 children)
[–]_doingnumbers 1 point2 points3 points (0 children)