eventemitter2
Advanced tools
Comparing version 0.0.1 to 0.1.0
@@ -0,11 +1,12 @@ | ||
;!function(exports, undefined) { | ||
;(function(exports, undefined) { | ||
exports.EventEmitter2 = EventEmitter2; | ||
var EventEmitter2 = exports.EventEmitter2 = function(conf) { | ||
if(conf) { | ||
if(conf.delimiter === '*') { | ||
function EventEmitter2(conf) { | ||
if (conf) { | ||
if (conf.delimiter === '*') { | ||
throw new Error('The event can not be delimited by the "*" (wild-card) character.'); | ||
} | ||
} | ||
this._delimiter = conf ? conf.delimiter : '/'; | ||
this._delimiter = conf ? conf.delimiter : '.'; | ||
this._maxListeners = conf ? conf.maxListeners : 10; | ||
@@ -15,4 +16,4 @@ this._events = {}; | ||
EventEmitter2.prototype.addListener = function(event, listener, ttl) { | ||
EventEmitter2.prototype.addListener = function(event, listener) { | ||
var name, ns = this._events; | ||
@@ -24,23 +25,13 @@ | ||
// the name has a delimiter | ||
if(~event.indexOf(this._delimiter)) { | ||
if (~event.indexOf(this._delimiter)) { | ||
//split the name into an array | ||
name = event.split(this._delimiter); | ||
//split the name into an array | ||
name = event.split(this._delimiter); | ||
// continue to build out additional namespaces and attach the listener to them | ||
for(var i = 0, l = name.length; i < l; i++) { | ||
// continue to build out additional namespaces and attach the listener to them | ||
for(var i = 0, l = name.length; i < l; i++) { | ||
// get the namespace | ||
ns = ns[name[i]] || (ns[name[i]] = {}); | ||
// if this is a wild card or the completed ns, add the event | ||
if(i === name.length - 1) { | ||
if(ns._listeners && ns._listeners.length === this.maxListeners) { | ||
this.emit('maxListeners', event); | ||
return; | ||
} | ||
ns._listeners ? ns._listeners.push(listener) : ns._listeners = [listener]; | ||
ns._ttl = ttl; | ||
} | ||
} | ||
// get the namespace | ||
ns = ns[name[i]] || (ns[name[i]] = {}); | ||
} | ||
} | ||
@@ -51,66 +42,72 @@ | ||
// get a handle to the event | ||
var e = ns[event] || (ns[event] = {}); | ||
// get a handle to the event | ||
ns = ns[event] || (ns[event] = {}); | ||
} | ||
e._listeners ? e._listeners.push(listener) : e._listeners = [listener]; | ||
e._ttl = ttl; | ||
if (ns._listeners && ns._listeners.length === this.maxListeners) { | ||
this.emit('maxListeners', event); | ||
return; | ||
} | ||
ns._listeners ? ns._listeners.push(listener) : ns._listeners = [listener]; | ||
}; | ||
EventEmitter2.prototype.on = EventEmitter2.prototype.addListener; | ||
EventEmitter2.prototype.once = function(event, listener) { | ||
this.addListener(event, listener, 1); | ||
this.many(event, listener, 1); | ||
}; | ||
EventEmitter2.prototype.emit = function(event) { | ||
EventEmitter2.prototype.many = function(event, listener, ttl) { | ||
var self = this; | ||
function invokeListeners(val, args) { | ||
if(val._ttl !== 0) { | ||
for (var k = 0, l = val._listeners.length; k < l; k++) { | ||
val._listeners[k].apply(this, args); | ||
val._ttl -= 1; | ||
} | ||
return true; | ||
this.addListener(event, function() { | ||
if(ttl-- == 0) { | ||
self.removeListener(event, listener); | ||
} | ||
else if(val._ttl === 0) { | ||
self.removeListener(val._listeners); // this seems wrong. | ||
else { | ||
listener.apply(null, arguments); | ||
} | ||
}); | ||
}; | ||
EventEmitter2.prototype.emit = function(event) { | ||
var self = this, args = arguments, i = 0, j = 0; | ||
function invokeListeners(val) { | ||
for (var k = 0, l = val._listeners.length; k < l; k++) { | ||
val._listeners[k].apply(this, args); | ||
} | ||
return true; | ||
} | ||
// get all the args except the event, make it a real array | ||
var args = arguments, i = 0, j = 0; | ||
// if there is a delimiter in the event name | ||
if(~event.indexOf(this._delimiter)) { | ||
//split the name into an array | ||
// If there is a delimiter in the event name | ||
if (~event.indexOf(this._delimiter)) { | ||
// Split the name into an array | ||
name = event.split(this._delimiter); | ||
var explore = [this._events], | ||
invoked = false, | ||
key = null; | ||
for (i = 0; i < name.length; i++) { | ||
// | ||
// Iterate over the parts of the potentially namespaced | ||
// event. | ||
// event. | ||
// | ||
// emit('foo/*/bazz') ==> ['foo', '*', 'bazz'] | ||
// emit('foo/*/bazz') ==> ['foo', '*', 'bazz'] | ||
// | ||
var part = name[i], | ||
newSets = [], | ||
removeAt = []; | ||
var part = name[i], | ||
newSets = []; | ||
for (j = 0; j < explore.length; j++) { | ||
// | ||
// Iterative "unkown" set exploration: Iterate over each "unknown" | ||
// set of objects in the events tree. If a wildcard is discovered, | ||
// set of objects in the events tree. If a wildcard is discovered, | ||
// append that object to the unknown set and continue exploration. | ||
// | ||
var ns = explore[j]; | ||
if (i === name.length - 1) { | ||
@@ -124,7 +121,9 @@ // | ||
for (key in ns) { | ||
// | ||
// Remark: This could cause some collisions for `_listeners`, and `_ttl`. | ||
// | ||
if (ns[key] && ns[key]._listeners) { | ||
invokeListeners(ns[key], args); | ||
if (ns.hasOwnProperty(key)) { | ||
// | ||
// Remark: This could cause some collisions for `_listeners`. | ||
// | ||
if (ns[key] && ns[key]._listeners) { | ||
invokeListeners(ns[key]); | ||
} | ||
} | ||
@@ -135,9 +134,8 @@ } | ||
else { | ||
if (ns[part] && ns[part]._listeners && invokeListeners(ns[part], args)) { | ||
if (ns[part] && ns[part]._listeners && invokeListeners(ns[part])) { | ||
invoked = true; | ||
} | ||
if (ns['*'] && ns['*']._listeners && invokeListeners(ns['*'], args)) { | ||
else if (ns['*'] && ns['*']._listeners && invokeListeners(ns['*'])) { | ||
invoked = true; | ||
} | ||
} | ||
} | ||
@@ -147,7 +145,8 @@ } | ||
if (part !== '*') { | ||
if (!ns[part] && !ns['*']) { | ||
// | ||
// If it's not a wild card and there isn't a wild | ||
// card stored and the exact key isn't at the | ||
// next step of the events object, break out | ||
// card stored and the exact key isn't at the | ||
// next step of the events object, break out | ||
// of the loop and end evaluation. | ||
@@ -157,3 +156,3 @@ // | ||
} | ||
if (ns[part]) { | ||
@@ -167,3 +166,3 @@ // | ||
} | ||
explore[j] = explore[j][part]; | ||
@@ -178,8 +177,8 @@ } | ||
explore[j] = explore[j]['*']; | ||
if (ns['*'] && ns['*']._listeners && invokeListeners(ns['*'], args)) { | ||
if (ns['*'] && ns['*']._listeners && invokeListeners(ns['*'])) { | ||
invoked = true; | ||
} | ||
} | ||
} | ||
} | ||
else { | ||
@@ -197,19 +196,12 @@ // | ||
} | ||
if (ns['*'] && ns['*']._listeners && invokeListeners(ns['*'], args)) { | ||
if (ns['*'] && ns['*']._listeners && invokeListeners(ns['*'])) { | ||
invoked = true; | ||
} | ||
removeAt.push(j); | ||
explore.splice(j, 1); | ||
} | ||
} | ||
} | ||
for (j = 0; j < removeAt.length; j++) { | ||
// | ||
// Remove stale sets that are no longer of interest. | ||
// | ||
explore.splice(j, 1); | ||
} | ||
if (newSets.length) { | ||
@@ -221,22 +213,12 @@ // | ||
explore = explore.concat(newSets); | ||
} | ||
} | ||
} | ||
return invoked; | ||
} | ||
// if the name does not have a delimiter | ||
else { | ||
if (!this._events[event]) { | ||
return false; | ||
} | ||
// get a handle to the listeners | ||
var listeners = this._events[event]._listeners || null; | ||
if (!listeners) { | ||
return false; | ||
} | ||
else if (this._events[event] && this._events[event]._listeners) { | ||
var listeners = this._events[event]._listeners; | ||
// fire off each of them | ||
@@ -250,92 +232,34 @@ for(i = 0, l = listeners.length; i < l; i++) { | ||
EventEmitter2.prototype.removeListener = function(event) { | ||
this.listeners(event, true); | ||
EventEmitter2.prototype.removeListener = function(event, listener) { | ||
if(listener && this._events[event] && this._events[event]._listeners) { | ||
// Make a reference to all the listeners for the event. | ||
var listeners = this._events[event]._listeners; | ||
// Loop through and check the signatures to find the exact listener to remove. | ||
for(var i = 0, l = listeners.length; i < l; i++) { | ||
if(listener === listeners[i]) { | ||
// Break out and return the removed listener. | ||
return listeners.splice(i, 1); | ||
} | ||
} | ||
} | ||
else { | ||
this._events[event] = {}; | ||
} | ||
}; | ||
EventEmitter2.prototype.removeAllListeners = function() { | ||
for(var event in this._events) { | ||
this.listeners(event, null, true); | ||
} | ||
}; | ||
EventEmitter2.prototype.removeAllListeners = function(){ this._events = {}; }; | ||
EventEmitter2.prototype.setMaxListeners = function(n) { | ||
this.maxListeners = n; | ||
} | ||
EventEmitter2.prototype.listeners = function(event, listener, removeAllListeners) { | ||
var listeners = [], i = 0, j = 0; // the array of listeners to return. | ||
// if there is a delimiter in the event name | ||
if(~event.indexOf(this._delimiter)) { | ||
//split the name into an array | ||
name = event.split(this._delimiter); | ||
// continue to build out additional namespaces and attach the listener to them | ||
for (i = 0; i < name.length; i++) { | ||
// get the namespace | ||
ns = ns[name[i]] || (ns[name[i]] = {}); | ||
// | ||
// if this is a wild card or the completed ns, remove the event, | ||
// also reset the times to live and the time to die. | ||
// | ||
if(ns._listeners) { | ||
// | ||
// if there is only one argument to this method, we are just | ||
// looking to see what listeners exist and then report on that. | ||
// | ||
if(arguments.length === 1) { | ||
listeners.push(ns._listeners); | ||
} else { | ||
// | ||
// if we have some arguments, we're considering deleteing some | ||
// or possibly all of the listeners associated with an event. | ||
// | ||
if(removeAllListeners) { | ||
ns = null; | ||
} | ||
else { | ||
for (j = 0; j < ns._listeners.length; j++) { | ||
if(ns._listeners[j] === listener) { | ||
ns = null; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
}; | ||
EventEmitter2.prototype.listeners = function(event) { | ||
if(this._events[event]) { | ||
return this._events[event]._listeners; | ||
} | ||
else { | ||
// | ||
// this is a simple event, no need to deconstruct the name, | ||
// lets just kill any listeners associated with it. | ||
// | ||
var e = this._events[event]; | ||
if(!removeEvents) { | ||
listeners.push(ns._listeners); | ||
} | ||
else { | ||
if(removeAllListeners) { | ||
e = null; | ||
} | ||
else { | ||
for (i = 0; i < e._listeners.length; i++) { | ||
if(e._listeners[i] === listener) { | ||
e = null; | ||
} | ||
} | ||
} | ||
} | ||
return false; | ||
} | ||
return listeners; | ||
}; | ||
}((typeof exports === 'undefined') ? window : exports)); | ||
}(typeof exports === 'undefined' ? window : exports); |
{ | ||
"name": "eventemitter2", | ||
"version": "0.0.1", | ||
"version": "0.1.0", | ||
"description": "A Node.js event emitter implementation with namespaces, wildcards, TTL and browser support", | ||
@@ -8,3 +8,4 @@ "keywords": ["event", "events", "emitter", "eventemitter"], | ||
"contributers" : [ | ||
"Charlie Robbins <charlie@nodejitsu.com> http://twitter.com/indexzero" | ||
"Charlie Robbins <charlie@nodejitsu.com> http://twitter.com/indexzero", | ||
"Fedor Indutny <fedor.indutny@gmail.com> http://www.twitter.com/indutny" | ||
], | ||
@@ -11,0 +12,0 @@ "licenses": [{"type": "MIT"}], |
@@ -1,2 +0,1 @@ | ||
**WORK IN PROGRESS** | ||
@@ -7,16 +6,27 @@ # EventEmitter2 | ||
## Motivation | ||
## Features | ||
- Namespaced events | ||
- Wildcards for namespaces | ||
- Times To Live (TTL), extends the `once` concept | ||
- Faster performance for emission and event registration | ||
- Run in the browser environment | ||
- Times To Listen (TTL), extends the `once` concept | ||
- Browser environment compatibility | ||
- As good or better performance for emission and listener registration as Node.js core EventEmitter | ||
- Smaller. EventEmitter2.js (2.2K Minified) VS. events.js (2.7K Minified) | ||
## Differences | ||
## Differences (Non breaking, compatible with existing EventEmitter) | ||
- Because wildcard events are supported, the first parameter of a listener is the actual event name that the listener reacted to. | ||
- The constructor takes a configuration object. | ||
```javascript | ||
var server = EventEmitter2({ | ||
delimiter: '/', // the delimiter used to segment namespaces, defaults to `.`. | ||
maxListeners: 20 // the max number of listeners that can be assigned to an event, defaults to 10. | ||
}); | ||
``` | ||
- The first parameter of a listener is the actual event name that the listener reacted to (because of wildcards). | ||
```javascript | ||
server.on('foo/*', function(event, value1, value2) { | ||
server.on('foo.*', function(event, value1, value2) { | ||
console.log('a values were', value1, value2); | ||
@@ -26,8 +36,8 @@ }); | ||
- Times To Live, an extension of the `once` concept. | ||
- A new method was adde. Times to listen, an extension of the `once` concept. | ||
```javascript | ||
server.on('foo/*', function(event, value1, value2) { | ||
server.many('foo', function(event, value1, value2) { | ||
console.log('a values were', value1, value2); | ||
}, 15); | ||
}, 4); | ||
``` | ||
@@ -47,4 +57,4 @@ | ||
#### emitter.addListener(event, listener [, ttl]) | ||
#### emitter.on(event, listener [, ttl]) | ||
#### emitter.addListener(event, listener) | ||
#### emitter.on(event, listener) | ||
@@ -76,3 +86,13 @@ Adds a listener to the end of the listeners array for the specified event. | ||
#### emitter.many(event, listener, timesToListen) | ||
Adds a listener that will execute **n times** for the event before being removed. The listener is invoked only the first time the event is fired, after which it is removed. | ||
```javascript | ||
server.many('get', function (value) { | ||
console.log('Ah, we have our first value!'); | ||
}, 4); | ||
``` | ||
#### emitter.removeListener(event, listener) | ||
@@ -117,2 +137,6 @@ | ||
## Test coverage | ||
There is a test suite that tries to cover each use case, it can be found <a href="https://github.com/hij1nx/EventEmitter2/tree/master/test">here</a>. | ||
## Licence | ||
@@ -122,3 +146,3 @@ | ||
Copyright (c) 2011 hij1nx <http://www.twitter.com/hij1nx>, indexzero <http://www.twitter.com/indexzero>, nodejitsu <http://www.twitter.com/nodejitsu> | ||
Copyright (c) 2011 hij1nx <http://www.twitter.com/hij1nx>, indexzero <http://www.twitter.com/indexzero>, Fedor Indutny <http://www.twitter.com/indutny> | ||
@@ -125,0 +149,0 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: |
@@ -115,7 +115,7 @@ | ||
emitter.on('test5/ns1', function () { | ||
emitter.on('test5.ns1', function () { | ||
test.ok(true, 'The event was raised'); | ||
}); | ||
emitter.emit('test5/ns1'); | ||
emitter.emit('test5.ns1'); | ||
test.done(); | ||
@@ -137,3 +137,3 @@ | ||
emitter.on('test6/ns1', function (event, value1) { | ||
emitter.on('test6.ns1', function (event, value1) { | ||
test.ok(true, 'The event was raised'); | ||
@@ -143,3 +143,3 @@ test.ok(typeof value1 !== 'undefined', 'The event was raised with the value `' + value1 + '`.'); | ||
emitter.emit('test6/ns1', 1); | ||
emitter.emit('test6.ns1', 1); | ||
test.done(); | ||
@@ -156,3 +156,3 @@ | ||
emitter.on('test7/ns1', function (event, value1, value2, value3) { | ||
emitter.on('test7.ns1', function (event, value1, value2, value3) { | ||
test.ok(true, 'The event was raised'); | ||
@@ -165,4 +165,4 @@ test.ok(arguments.length === 4, 'The event was raised with the correct number of arguments'); | ||
emitter.emit('test7/ns1', 1, 2, 3); | ||
emitter.emit('test7/ns1', 4, 5, 6); | ||
emitter.emit('test7.ns1', 1, 2, 3); | ||
emitter.emit('test7.ns1', 4, 5, 6); | ||
@@ -185,7 +185,7 @@ test.done(); | ||
emitter.on('test8/*', function () { | ||
emitter.on('test8.*', function () { | ||
test.ok(true, 'The event was raised'); | ||
}); | ||
emitter.emit('test8/ns1'); | ||
emitter.emit('test8.ns1'); | ||
@@ -208,7 +208,7 @@ test.done(); | ||
emitter.on('test9/ns1', function () { | ||
emitter.on('test9.ns1', function () { | ||
test.ok(true, 'The event was raised'); | ||
}); | ||
emitter.emit('test9/*'); | ||
emitter.emit('test9.*'); | ||
@@ -231,7 +231,7 @@ test.done(); | ||
emitter.on('test10/*/foo', function () { | ||
emitter.on('test10.*.foo', function () { | ||
test.ok(true, 'The event was raised'); | ||
}); | ||
emitter.emit('test10/ns1/foo'); | ||
emitter.emit('test10.ns1.foo'); | ||
@@ -254,7 +254,7 @@ test.done(); | ||
emitter.on('test11/ns1/foo', function () { | ||
emitter.on('test11.ns1.foo', function () { | ||
test.ok(true, 'The event was raised'); | ||
}); | ||
emitter.emit('test11/*/foo'); | ||
emitter.emit('test11.*.foo'); | ||
@@ -277,3 +277,3 @@ test.done(); | ||
emitter.on('test7/ns1/ns2', function (event, value1, value2, value3) { | ||
emitter.on('test12.ns1.ns2', function (event, value1, value2, value3) { | ||
test.ok(true, 'The event was raised'); | ||
@@ -286,9 +286,36 @@ test.ok(arguments.length === 4, 'The event was raised with the correct number of arguments'); | ||
emitter.emit('test7/*/ns2', 1, 2, 3); | ||
emitter.emit('test7/*/ns2', 4, 5, 6); | ||
emitter.emit('test12.*.ns2', 1, 2, 3); | ||
emitter.emit('test12.*.ns2', 4, 5, 6); | ||
test.done(); | ||
}, | ||
'13. List all the listeners for a particular event.': function(test) { | ||
var EventEmitter2; | ||
if(typeof require !== 'undefined') { | ||
EventEmitter2 = require('../EventEmitter2').EventEmitter2; | ||
} | ||
else { | ||
EventEmitter2 = window.EventEmitter2; | ||
} | ||
var emitter = new EventEmitter2(); | ||
emitter.on('test13', function (event) { | ||
console.log('1'); | ||
}); | ||
emitter.on('test13', function (event) { | ||
console.log('2'); | ||
}); | ||
var listeners = emitter.listeners('test13'); | ||
test.ok(listeners.length === 2, 'The event `test13` should have 2 listeners'); | ||
test.done(); | ||
} | ||
}; |
@@ -27,8 +27,104 @@ | ||
}, | ||
'1. A listener with a TTL of 10 should only listen 10 times.': function (test) { | ||
'2. A listener with a TTL of 4 should only listen 4 times.': function (test) { | ||
test.ok(true, 'everythings ok'); | ||
var EventEmitter2; | ||
if(typeof require !== 'undefined') { | ||
EventEmitter2 = require('../EventEmitter2').EventEmitter2; | ||
} | ||
else { | ||
EventEmitter2 = window.EventEmitter2; | ||
} | ||
var emitter = new EventEmitter2, count = 0; | ||
emitter.on('test1', function (event, value1) { | ||
test.ok(count <= 4, 'The event was raised 4 times.'); | ||
count++; | ||
}, 4); | ||
emitter.emit('test1', 1); | ||
emitter.emit('test1', 2); | ||
emitter.emit('test1', 3); | ||
emitter.emit('test1', 4); | ||
emitter.emit('test1', 5); | ||
test.done(); | ||
} | ||
}, | ||
'3. A listener with a TTL of 4 should only listen 4 times and pass parameters.': function (test) { | ||
var EventEmitter2; | ||
if(typeof require !== 'undefined') { | ||
EventEmitter2 = require('../EventEmitter2').EventEmitter2; | ||
} | ||
else { | ||
EventEmitter2 = window.EventEmitter2; | ||
} | ||
var emitter = new EventEmitter2, count = 0; | ||
emitter.on('test1', function (event, value1, value2, value3) { | ||
test.ok(typeof value1 !== 'undefined', 'got value 1'); | ||
test.ok(typeof value2 !== 'undefined', 'got value 2'); | ||
test.ok(typeof value3 !== 'undefined', 'got value 3'); | ||
test.ok(count <= 4, 'The event was raised 4 times.'); | ||
count++; | ||
}, 4); | ||
emitter.emit('test1', 1, 'A', false); | ||
emitter.emit('test1', 2, 'A', false); | ||
emitter.emit('test1', 3, 'A', false); | ||
emitter.emit('test1', 4, 'A', false); | ||
emitter.emit('test1', 5, 'A', false); | ||
test.done(); | ||
}, | ||
'3. Remove an event listener by signature.': function (test) { | ||
var EventEmitter2; | ||
if(typeof require !== 'undefined') { | ||
EventEmitter2 = require('../EventEmitter2').EventEmitter2; | ||
} | ||
else { | ||
EventEmitter2 = window.EventEmitter2; | ||
} | ||
var emitter = new EventEmitter2, count = 0; | ||
function f1(event) { | ||
"event A"; | ||
test.ok(count < 3, 'The event was raised less than 3 times.'); | ||
count++; | ||
} | ||
emitter.on('test1', f1); | ||
function f2(event) { | ||
"event B"; | ||
test.ok(count < 3, 'The event was raised less than 3 times.'); | ||
count++; | ||
} | ||
emitter.on('test1', f2); | ||
function f3(event) { | ||
"event C"; | ||
test.ok(count < 3, 'The event was raised less than 3 times.'); | ||
count++; | ||
} | ||
emitter.on('test1', f3); | ||
emitter.removeListener('test1', f2); | ||
emitter.emit('test1'); | ||
test.done(); | ||
} | ||
}; |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
463358
12
2213
148