A Signal is similar to an Event Emitter/Dispatcher or a Pub/Sub system, the main difference is that each event type has its own controller and doesn't rely on strings to broadcast/subscribe to events. To know more about the differences and advantages/disadvantages of each approach check the Wiki page.
This implementation is heavily inspired by Robert Penner's AS3-Signals but it is NOT a direct port, it has a different set of features (some extras and some missing) and some methods were renamed to avoid confusions and/or for brevity. It also borrows some ideas from Joa Ebert AS3-Signals fork.
The intention of this library is to be a "small brick" that can be used together with other libraries and frameworks, helping people to develop evented applications easily!
Advantages
-
Doesn't rely on strings for subscribing/publishing to a event type:
- Trying to dispatch or listen to an event type that doesn't exist throws errors instead of failing silently which helps to identify errors early.
- Code completion friendly.
- Arbitrary number of parameters to event handlers.
- Easy control of the event broadcaster and subscriber, avoiding that the wrong objects reacts to the event.
-
Convenience methods that usually aren't present on other implementations of the observer pattern like:
- Enable/disable event dispatching per event type.
- Remove all event listeners attached to a specific event type.
- Option to automatically remove listener after first execution.
- Option to bind an execution context to the event handler, avoiding scope issues.
- Remove/detach anonymous listener.
- Etc...
- Favor composition over inheritance.
- Easy to identify which event types the object dispatch.
Check Comparison between different Obeserver Pattern implementations for more details.
Basic Example
//custom object that dispatch a `started` signal var myObject = { started : new signals.Signal() }; function onStarted(param1, param2){ alert(param1 + param2); } myObject.started.add(onStarted); //add listener myObject.started.dispatch('foo', 'bar'); //dispatch signal passing custom parameters myObject.started.remove(onStarted); //remove a single listener
For more examples check the examples page on the wiki.
Naming convention
It is recommended to always name a signal on the past tense. This convention was based on the AS3-Signals recommendation, the reasoning behind it is to avoid confusions with regular properties and to keep consistency. Try combining multiple words if the event you are trying to describe doesn't have a past tense form or if you have naming collisions.
- Good Names:
- canceled
- clicked
- ended
- startedAnimation
- "Bad" Names:
- cancel (action names should be used for methods)
- onClick (reminds a DOM1 event handler, you may think the property is a function)
- ending (action is still happening, you aren't sure if event is dispatched at begin or end of action)
- animationStart (name doesn't represent an event, could be used to store any kind of value like a timestamp of when animation started, number representing the second when animation should start, a cue point, etc...)
Another option is to place all your signals inside an
object named on
following the DART DOM Events API.
That way it will be clear that each member is an event
type, it will avoid cluttering your object and make
naming easier.
References
More Info
The focus of this library is for custom events, there are no plans to add native DOM events support (AS3-signals has a NativeSignal class that emulates native flash events) specially since most of the JavaScript frameworks already have some kind of facade on top of the native events and also because of the differences between browsers. This feature should be implemented as a plugin or as a separate project.
Contributors and ideas are welcome!
License
Author
Bugs / Feature Request
Use github issue tracker to submit bugs and feature requests.
Download
You can download this project in either zip or tar formats. You can also clone the project with Git by running:
$ git clone git://github.com/millermedeiros/js-signals
Or install it on node using npm:
$ npm install signals