Skip to content

Instantly share code, notes, and snippets.

@ysndr
Last active August 29, 2015 14:06
Show Gist options
  • Save ysndr/813449af4a6c05b2cede to your computer and use it in GitHub Desktop.
Save ysndr/813449af4a6c05b2cede to your computer and use it in GitHub Desktop.
EnhancedEventEmitter (E3) for Node.js
/**
* Description: Slightly extended EventEmitter. Ported from Node.js/events.js
* Author: y4ng0 @ yangodev
* Licence: MIT
*/
/**
* EventEmitter class
* Creates an object with event registering and firing methods
*/
function E3(){/* costructor */}
module.exports = E3
E3.create = function (options) {
var e3 = new E3()
e3.init(options)
//delete e3.init
return e3
}
E3.emitter = E3.prototype
// helper variables
var isArray = Array.isArray,
keys = Object.keys
E3.prototype = {}
E3.prototype.constructor = E3
E3.prototype.DEFAULT_MODIFIER = null
E3.prototype._initialized = false
E3.prototype._events = null
// TODO rename to "subscribe"
E3.prototype.init = function init() {
if (this._initialized) return this
this.config.apply(this, arguments)
this._events = {}
this._initialized = true
return this
}
E3.prototype.config = function config(options){
options = options || {}
this.DEFAULT_MODIFIER = options.DEFAULT_MODIFIER || 'any'
return this
}
E3.prototype.receive = function receive(declaration) {
var event = null,
modifier = null,
receiver = null
event = declaration.event || event
modifier = declaration.mod ||
declaration.modifier ||
this.DEFAULT_MODIFIER
receiver = declaration.receiver ||
declaration.listener ||
receiver
if (!event) // Throw Error
throw new Error('receive needs an event to listen on.')
if ('function' !== typeof receiver) // Throw Error
throw new Error('receive only takes instances of Function as receiver / listener');
// To avoid recursion in the case that event == "newReceiver"!
// before adding it to the listeners, first emit "newReceiver"
this.send({
event: 'newReceiver',
data: {
event: event,
modifier: (modifier === this.DEFAULT_MODIFIER) ? modifier + '(Default)' : modifier,
receiver: receiver
}
})
if (!this._events[event]) {
this._events[event] = {}
}
if (!this._events[event][modifier]) {
this._events[event][modifier] = []
}
// at this point this._events[event][modifier] is an Array we can push to!
this._events[event][modifier].push(receiver)
return this
}
E3.prototype.send = function (declaration) {
var event = null,
modifier = null,
data = null,
args = null,
respond_data = false,
response = [],
final = function(){}
event = declaration.event || event
event = ('string' === typeof arguments[0]) ? arguments[0] : event
modifier = declaration.mod || declaration.modifier || []
modifier = [this.DEFAULT_MODIFIER].concat(modifier)
data = declaration.data || data
args = declaration.args || [] // given Array will be parsed to CallBack / listener as arguments
if (!isArray(args)) args = [].concat(args)
respond_data = declaration.respond_data || respond_data
final = declaration.final || final
if (!event) { // Throw Error
throw new Error('You have to define the argument to fire on!')
}
// Setting up data Array
if (!data && arguments.length > 1) {
var l = arguments.length
for (var i = 1; i < l; i++) args.push(arguments[i])
}
if (data) args.push(data)
if (!this._events[event]) return this
var handler = this._events[event]
for (var m = 0, l = modifier.length; m < l; m++) {
if (handler[modifier[m]]) {
handler[modifier[m]].forEach(function (listener) {
response.push(listener.apply(this, args))
})
}
}
final(response)
return (respond_data) ? response : this //just to be sure
}
E3.prototype.once = function (declaration) {
var event = null,
modifier = null,
listener = null,
self = this
event = declaration.event || null
modifier = declaration.mod || declaration.modifier || modifier
listener = declaration.listener || declaration.receiver || listener
if (!event || !listener) {
throw new Error("You have to define at least en event + listner function") }
var remover = function(){
self.remove(rObj)
listener.apply(self, arguments)
}
var rObj = {
event: event,
mod : modifier,
listener : remover
}
this.receive(rObj)
return this
}
E3.prototype.remove = function remove(declaration) {
var event = null,
modifier = null,
receiver = null,
wipe = null
if(!declaration || !declaration.event){
this._events = {}
return this } // performs a fulll reset (wipes ALL events)
event = declaration.event || event
modifier = declaration.mod ||
declaration.modifier ||
this.DEFAULT_MODIFIER
receiver = declaration.receiver ||
declaration.listener ||
receiver
wipe = declaration.wipe || wipe
if (receiver && 'function' !== typeof receiver) { // Throw Error
throw new Error('remove() only takes instances of Function' +
'as receiver / listener')
}
if (!this._events[event]) return this
if (modifier === this.DEFAULT_MODIFIER && wipe) {
this._events[event] = {}
}
if ('function' === typeof this._events[event]) {
delete this._events[event]
return this
}
if (receiver) {
var list = this._events[event][modifier],
position = -1
for (var i = 0, l = list.length; i < l; i++) {
if (list[i] === receiver) {
position = i
break
}
}
if (position < 0) return this
list.splice(position, 1)
if (list.length == 0) {
delete this._events[event][modifier]
}
} else {
delete this._events[event][modifier]
}
return this
}
E3.prototype.list = function(event, modifier){
event = event || null
modifier = [].concat(modifier) || null
var output = {}
if (!event) return this._events // returns all events by default
if ('string' === typeof event && // will search the event node on _events
this._events[event]){
output = this._events[event] }
else if (isArray(event)){
event.forEach(function(event){
if(this._events[event]) output[event] = this._events[event]
})
} // extract all searched events from _events
else {
throw new Error('You have to set either nothing, '
+ ' a representing string'
+ 'or an array of strings as argument') } // throws an error when event not valid
// Deletes all modifier (sub)nodes on every output node
// that are not required
if (modifier){
keys(output).forEach(function(key){
keys(output[key])(function(mod){
if (modifier.indexOf(mod) < 0 && modifier.length > 0){
delete output[key][mod]
}
})
if (keys(output[key]).length < 1) delete output[key]
})
}
return output
}
/**
TODO:
Fallback to Node.js default functionality
*/
{
"name": "E3",
"version": "0.0.3",
"description": "Enhanced EventEmitter (E3) for node.js",
"main": "E3.js",
"directories": {
"test": "tests"
},
"repository": {
"type": "git",
"url": "git://gist.github.com/813449af4a6c05b2cede.git"
},
"keywords": [
"Enhanced",
"Event",
"Emitter",
"E3"
],
"author": "y4ng0 @ yangodev",
"license": "MIT",
"bugs": {
"url": "https://gist.github.com/yangodev/813449af4a6c05b2cede"
},
"url": "git://gist.github.com/813449af4a6c05b2cede.git",
"homepage": "https://gist.github.com/yangodev/813449af4a6c05b2cede"
}
@ysndr
Copy link
Author

ysndr commented Sep 13, 2014

Simple EventEmitter based on and extended from Node.js events.js / EventEmitter

Used a simplified version by ericz (https://github.com/ericz/EventEmitter/blob/master/EventEmitter.js)


How to use it:

  • Set it up
var E3 = require(E3),
emitter = E3.create()
  • Receive Evemts
emitter.receive({
  event : 'foo',
  modifier : 'bar',
  receiver : function(name){
    console.log('Hello, ' + name)
  }
})
  • Emit Events
emitter.send({
  event : 'foo',
  modifier : 'bar",
  data : 'John Doe' 
})

>>> Hello, John Doe
  • List Events
emitter.list([event][modifier])
  • Remove Events
emitter.remove()
>>> flushes all receivers

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