mbus
Version:
If Node's EventEmitter and Eve were to have a child, it might look something like this
174 lines (130 loc) • 3.8 kB
JavaScript
var reDelim = /[\.\:]/;
/**
# mbus
If Node's EventEmitter and Eve were to have a child, it might look something like this.
No wildcard support at this stage though...
## Example Usage
<<< docs/usage.md
## Reference
### `mbus(namespace?, parent?, scope?)`
Create a new message bus with `namespace` inheriting from the `parent`
mbus instance. If events from this message bus should be triggered with
a specific `this` scope, then specify it using the `scope` argument.
**/
var createBus = module.exports = function(namespace, parent, scope) {
var registry = {};
var feeds = [];
function bus(name) {
var args = [].slice.call(arguments, 1);
var delimited = normalize(name);
var handlers = registry[delimited] || [];
var results;
// send through the feeds
feeds.forEach(function(feed) {
feed({ name: delimited, args: args });
});
// run the registered handlers
results = [].concat(handlers).map(function(handler) {
return handler.apply(scope || this, args);
});
// run the parent handlers
if (bus.parent) {
results = results.concat(
bus.parent.apply(
scope || this,
[(namespace ? namespace + '.' : '') + delimited].concat(args)
)
);
}
return results;
}
/**
### `mbus#clear()`
Reset the handler registry, which essential deregisters all event listeners.
_Alias:_ `removeAllListeners`
**/
function clear(name) {
// if we have a name, reset handlers for that handler
if (name) {
delete registry[normalize(name)];
}
// otherwise, reset the entire handler registry
else {
registry = {};
}
}
/**
### `mbus#feed(handler)`
Attach a handler function that will see all events that are sent through
this bus in an "object stream" format that matches the following format:
```
{ name: 'event.name', args: [ 'event', 'args' ] }
```
The feed function returns a function that can be called to stop the feed
sending data.
**/
function feed(handler) {
function stop() {
feeds.splice(feeds.indexOf(handler), 1);
}
feeds.push(handler);
return stop;
}
function normalize(name) {
return (Array.isArray(name) ? name : name.split(reDelim)).join('.');
}
/**
### `mbus#off(name, handler)`
Deregister an event handler.
**/
function off(name, handler) {
var handlers = registry[normalize(name)] || [];
var idx = handlers ? handlers.indexOf(handler._actual || handler) : -1;
if (idx >= 0) {
handlers.splice(idx, 1);
}
}
/**
### `mbus#on(name, handler)`
Register an event handler for the event `name`.
**/
function on(name, handler) {
var handlers;
name = normalize(name);
handlers = registry[name];
if (handlers) {
handlers.push(handler);
}
else {
registry[name] = [ handler ];
}
return bus;
}
/**
### `mbus#once(name, handler)`
Register an event handler for the event `name` that will only
trigger once (i.e. the handler will be deregistered immediately after
being triggered the first time).
**/
function once(name, handler) {
function handleEvent() {
var result = handler.apply(this, arguments);
bus.off(name, handleEvent);
return result;
}
handler._actual = handleEvent;
return on(name, handleEvent);
}
if (typeof namespace == 'function') {
parent = namespace;
namespace = '';
}
namespace = normalize(namespace || '');
bus.clear = bus.removeAllListeners = clear;
bus.feed = feed;
bus.on = bus.addListener = on;
bus.once = once;
bus.off = bus.removeListener = off;
bus.parent = parent || (namespace && createBus());
return bus;
};