Package Exports
- nextgen-events
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (nextgen-events) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
NextGen Events
Next generation of events handling for node.js
- License: MIT
- Current status: beta
- Platform: Node.js only (browser support is planned)
TOC
- Basic synchronous event-emitting (node-compatible)
- Basic synchronous event-emitting (NOT compatible with node)
- Next Gen feature: async emitting
- Next Gen feature: contexts
- Next Gen feature: contexts queue
- Next Gen feature: contexts serialization
Basic synchronous event-emitting (node-compatible)
should add one listener and emit should trigger it, using 'new'.
var bus = new NextGenEvents() ;
var triggered = 0 ;
bus.on( 'hello' , function() { triggered ++ ; } ) ;
bus.emit( 'hello' ) ;
expect( triggered ).to.be( 1 ) ;should add one listener and emit should trigger it, using 'Object.create()'.
var bus = Object.create( NextGenEvents.prototype ) ;
var triggered = 0 ;
bus.on( 'hello' , function() { triggered ++ ; } ) ;
bus.emit( 'hello' ) ;
expect( triggered ).to.be( 1 ) ;should emit with argument.
var bus = Object.create( NextGenEvents.prototype ) ;
var triggered = 0 ;
bus.on( 'hello' , function( arg1 , arg2 ) {
triggered ++ ;
expect( arg1 ).to.be( 'world' ) ;
expect( arg2 ).to.be( '!' ) ;
} ) ;
bus.emit( 'hello' , 'world' , '!' ) ;
expect( triggered ).to.be( 1 ) ;should add many basic listeners for many events, and multiple emits should trigger only relevant listener.
var bus = Object.create( NextGenEvents.prototype ) ;
var onFoo1 , onBar1 , onBar2 , onBaz1 , onBaz2 , onBaz3 ;
var triggered = { foo1: 0 , bar1: 0 , bar2: 0 , baz1: 0 , baz2: 0 , baz3: 0 , qux: 0 } ;
// 1 listener for 'foo'
bus.on( 'foo' , onFoo1 = function() { triggered.foo1 ++ ; } ) ;
// 2 listeners for 'bar'
bus.on( 'bar' , onBar1 = function() { triggered.bar1 ++ ; } ) ;
bus.on( 'bar' , onBar2 = function() { triggered.bar2 ++ ; } ) ;
// 3 listeners for 'baz'
bus.on( 'baz' , onBaz1 = function() { triggered.baz1 ++ ; } ) ;
bus.on( 'baz' , onBaz2 = function() { triggered.baz2 ++ ; } ) ;
bus.on( 'baz' , onBaz3 = function() { triggered.baz3 ++ ; } ) ;
bus.emit( 'foo' ) ;
expect( triggered ).to.eql( { foo1: 1 , bar1: 0 , bar2: 0 , baz1: 0 , baz2: 0 , baz3: 0 , qux: 0 } ) ;
bus.emit( 'bar' ) ;
expect( triggered ).to.eql( { foo1: 1 , bar1: 1 , bar2: 1 , baz1: 0 , baz2: 0 , baz3: 0 , qux: 0 } ) ;
bus.emit( 'baz' ) ;
expect( triggered ).to.eql( { foo1: 1 , bar1: 1 , bar2: 1 , baz1: 1 , baz2: 1 , baz3: 1 , qux: 0 } ) ;
bus.emit( 'qux' ) ;
expect( triggered ).to.eql( { foo1: 1 , bar1: 1 , bar2: 1 , baz1: 1 , baz2: 1 , baz3: 1 , qux: 0 } ) ;
bus.emit( 'foo' ) ;
bus.emit( 'foo' ) ;
expect( triggered ).to.eql( { foo1: 3 , bar1: 1 , bar2: 1 , baz1: 1 , baz2: 1 , baz3: 1 , qux: 0 } ) ;
bus.emit( 'qux' ) ;
bus.emit( 'qux' ) ;
expect( triggered ).to.eql( { foo1: 3 , bar1: 1 , bar2: 1 , baz1: 1 , baz2: 1 , baz3: 1 , qux: 0 } ) ;
bus.emit( 'baz' ) ;
bus.emit( 'baz' ) ;
expect( triggered ).to.eql( { foo1: 3 , bar1: 1 , bar2: 1 , baz1: 3 , baz2: 3 , baz3: 3 , qux: 0 } ) ;should add and remove listeners.
var bus = Object.create( NextGenEvents.prototype ) ;
var onFoo1 , onBar1 , onBar2 , onBaz1 , onBaz2 , onBaz3 ;
var triggered = { foo1: 0 , bar1: 0 , bar2: 0 , baz1: 0 , baz2: 0 , baz3: 0 , qux: 0 } ;
// 1 listener for 'foo'
bus.on( 'foo' , onFoo1 = function() { triggered.foo1 ++ ; } ) ;
// 2 listeners for 'bar'
bus.on( 'bar' , onBar1 = function() { triggered.bar1 ++ ; } ) ;
bus.on( 'bar' , onBar2 = function() { triggered.bar2 ++ ; } ) ;
// 3 listeners for 'baz'
bus.on( 'baz' , onBaz1 = function() { triggered.baz1 ++ ; } ) ;
bus.on( 'baz' , onBaz2 = function() { triggered.baz2 ++ ; } ) ;
bus.on( 'baz' , onBaz3 = function() { triggered.baz3 ++ ; } ) ;
bus.emit( 'foo' ) ;
expect( triggered ).to.eql( { foo1: 1 , bar1: 0 , bar2: 0 , baz1: 0 , baz2: 0 , baz3: 0 , qux: 0 } ) ;
bus.emit( 'bar' ) ;
expect( triggered ).to.eql( { foo1: 1 , bar1: 1 , bar2: 1 , baz1: 0 , baz2: 0 , baz3: 0 , qux: 0 } ) ;
bus.removeListener( 'bar' , onBar2 ) ;
bus.emit( 'bar' ) ;
expect( triggered ).to.eql( { foo1: 1 , bar1: 2 , bar2: 1 , baz1: 0 , baz2: 0 , baz3: 0 , qux: 0 } ) ;
bus.removeListener( 'bar' , onBar2 ) ;
bus.emit( 'bar' ) ;
expect( triggered ).to.eql( { foo1: 1 , bar1: 3 , bar2: 1 , baz1: 0 , baz2: 0 , baz3: 0 , qux: 0 } ) ;
bus.removeListener( 'foo' , onBar1 ) ; // Not listening for this event!
bus.removeListener( 'bar' , function() {} ) ; // Not event registered
bus.emit( 'foo' ) ;
bus.emit( 'bar' ) ;
expect( triggered ).to.eql( { foo1: 2 , bar1: 4 , bar2: 1 , baz1: 0 , baz2: 0 , baz3: 0 , qux: 0 } ) ;.removeAllListeners() should remove all listeners for an event.
var bus = Object.create( NextGenEvents.prototype ) ;
var onFoo1 , onBar1 , onBar2 , onBaz1 , onBaz2 , onBaz3 ;
var triggered = { foo1: 0 , bar1: 0 , bar2: 0 , baz1: 0 , baz2: 0 , baz3: 0 , qux: 0 } ;
// 1 listener for 'foo'
bus.on( 'foo' , onFoo1 = function() { triggered.foo1 ++ ; } ) ;
// 2 listeners for 'bar'
bus.on( 'bar' , onBar1 = function() { triggered.bar1 ++ ; } ) ;
bus.on( 'bar' , onBar2 = function() { triggered.bar2 ++ ; } ) ;
// 3 listeners for 'baz'
bus.on( 'baz' , onBaz1 = function() { triggered.baz1 ++ ; } ) ;
bus.on( 'baz' , onBaz2 = function() { triggered.baz2 ++ ; } ) ;
bus.on( 'baz' , onBaz3 = function() { triggered.baz3 ++ ; } ) ;
bus.emit( 'foo' ) ;
bus.emit( 'bar' ) ;
bus.emit( 'baz' ) ;
expect( triggered ).to.eql( { foo1: 1 , bar1: 1 , bar2: 1 , baz1: 1 , baz2: 1 , baz3: 1 , qux: 0 } ) ;
bus.removeAllListeners( 'bar' ) ;
bus.emit( 'bar' ) ;
expect( triggered ).to.eql( { foo1: 1 , bar1: 1 , bar2: 1 , baz1: 1 , baz2: 1 , baz3: 1 , qux: 0 } ) ;
bus.emit( 'foo' ) ;
expect( triggered ).to.eql( { foo1: 2 , bar1: 1 , bar2: 1 , baz1: 1 , baz2: 1 , baz3: 1 , qux: 0 } ) ;
bus.removeAllListeners( 'baz' ) ;
bus.emit( 'foo' ) ;
bus.emit( 'bar' ) ;
bus.emit( 'baz' ) ;
expect( triggered ).to.eql( { foo1: 3 , bar1: 1 , bar2: 1 , baz1: 1 , baz2: 1 , baz3: 1 , qux: 0 } ) ;.removeAllListeners() without argument should all listeners for all events.
var bus = Object.create( NextGenEvents.prototype ) ;
var onFoo1 , onBar1 , onBar2 , onBaz1 , onBaz2 , onBaz3 ;
var triggered = { foo1: 0 , bar1: 0 , bar2: 0 , baz1: 0 , baz2: 0 , baz3: 0 , qux: 0 } ;
// 1 listener for 'foo'
bus.on( 'foo' , onFoo1 = function() { triggered.foo1 ++ ; } ) ;
// 2 listeners for 'bar'
bus.on( 'bar' , onBar1 = function() { triggered.bar1 ++ ; } ) ;
bus.on( 'bar' , onBar2 = function() { triggered.bar2 ++ ; } ) ;
// 3 listeners for 'baz'
bus.on( 'baz' , onBaz1 = function() { triggered.baz1 ++ ; } ) ;
bus.on( 'baz' , onBaz2 = function() { triggered.baz2 ++ ; } ) ;
bus.on( 'baz' , onBaz3 = function() { triggered.baz3 ++ ; } ) ;
bus.emit( 'foo' ) ;
bus.emit( 'bar' ) ;
bus.emit( 'baz' ) ;
expect( triggered ).to.eql( { foo1: 1 , bar1: 1 , bar2: 1 , baz1: 1 , baz2: 1 , baz3: 1 , qux: 0 } ) ;
bus.removeAllListeners() ;
bus.emit( 'foo' ) ;
bus.emit( 'bar' ) ;
bus.emit( 'baz' ) ;
bus.emit( 'qux' ) ;
expect( triggered ).to.eql( { foo1: 1 , bar1: 1 , bar2: 1 , baz1: 1 , baz2: 1 , baz3: 1 , qux: 0 } ) ;.once() should add one time listener for an event, the event should stop listening after being triggered once.
var bus = Object.create( NextGenEvents.prototype ) ;
var onFoo1 , onBar1 , onBar2 , onBaz1 , onBaz2 , onBaz3 ;
var triggered = { foo1: 0 , bar1: 0 , bar2: 0 , baz1: 0 , baz2: 0 , qux: 0 } ;
// 1 listener for 'foo'
bus.once( 'foo' , onFoo1 = function() { triggered.foo1 ++ ; } ) ;
// 2 listeners for 'bar'
bus.on( 'bar' , onBar1 = function() { triggered.bar1 ++ ; } ) ;
bus.once( 'bar' , onBar2 = function() { triggered.bar2 ++ ; } ) ;
// 3 listeners for 'baz'
bus.on( 'baz' , onBaz1 = function() { triggered.baz1 ++ ; } ) ;
onBaz2 = function() { triggered.baz2 ++ ; } ;
bus.once( 'baz' , onBaz2 ) ;
bus.once( 'baz' , onBaz2 ) ;
bus.once( 'baz' , onBaz2 ) ;
bus.emit( 'foo' ) ;
bus.emit( 'bar' ) ;
bus.emit( 'baz' ) ;
expect( triggered ).to.eql( { foo1: 1 , bar1: 1 , bar2: 1 , baz1: 1 , baz2: 3 , qux: 0 } ) ;
bus.emit( 'foo' ) ;
expect( triggered ).to.eql( { foo1: 1 , bar1: 1 , bar2: 1 , baz1: 1 , baz2: 3 , qux: 0 } ) ;
bus.emit( 'bar' ) ;
expect( triggered ).to.eql( { foo1: 1 , bar1: 2 , bar2: 1 , baz1: 1 , baz2: 3 , qux: 0 } ) ;
bus.emit( 'baz' ) ;
expect( triggered ).to.eql( { foo1: 1 , bar1: 2 , bar2: 1 , baz1: 2 , baz2: 3 , qux: 0 } ) ;unhandled 'error' event should throw whatever is passed to it.
var throwed = 0 , triggered = 0 ;
var bus = Object.create( NextGenEvents.prototype ) ;
var testError = new Error( 'Some error occurs!' ) ;
var onError = function( error ) {
triggered ++ ;
expect( error ).to.be( testError ) ;
} ;
try {
bus.emit( 'error' , testError ) ;
}
catch ( error ) {
throwed ++ ;
expect( error ).to.be( testError ) ;
}
expect( throwed ).to.be( 1 ) ;
bus.once( 'error' , onError ) ;
bus.emit( 'error' , testError ) ;
// Should not throw
expect( triggered ).to.be( 1 ) ;
try {
bus.emit( 'error' , testError ) ;
}
catch ( error ) {
throwed ++ ;
expect( error ).to.be( testError ) ;
}
expect( throwed ).to.be( 2 ) ;NextGenEvents.listenerCount() should count listeners for an event.
var bus = Object.create( NextGenEvents.prototype ) ;
var onFoo1 ;
onFoo1 = function() {} ;
bus.on( 'foo' , onFoo1 ) ;
expect( NextGenEvents.listenerCount( bus , 'foo' ) ).to.be( 1 ) ;
expect( NextGenEvents.listenerCount( bus , 'bar' ) ).to.be( 0 ) ;
bus.on( 'foo' , onFoo1 ) ;
bus.on( 'foo' , onFoo1 ) ;
expect( NextGenEvents.listenerCount( bus , 'foo' ) ).to.be( 3 ) ;
expect( NextGenEvents.listenerCount( bus , 'bar' ) ).to.be( 0 ) ;
bus.removeListener( 'foo' , onFoo1 ) ;
expect( NextGenEvents.listenerCount( bus , 'foo' ) ).to.be( 0 ) ;
expect( NextGenEvents.listenerCount( bus , 'bar' ) ).to.be( 0 ) ;
bus.once( 'foo' , onFoo1 ) ;
expect( NextGenEvents.listenerCount( bus , 'foo' ) ).to.be( 1 ) ;
expect( NextGenEvents.listenerCount( bus , 'bar' ) ).to.be( 0 ) ;
bus.emit( 'foo' ) ;
expect( NextGenEvents.listenerCount( bus , 'foo' ) ).to.be( 0 ) ;
expect( NextGenEvents.listenerCount( bus , 'bar' ) ).to.be( 0 ) ;Basic synchronous event-emitting (NOT compatible with node)
should remove every occurences of a listener for one event.
var bus = Object.create( NextGenEvents.prototype ) ;
var onFoo1 , onBar1 , onBar2 ;
var triggered = { foo1: 0 , bar1: 0 , bar2: 0 } ;
onFoo1 = function() { triggered.foo1 ++ ; } ;
onBar1 = function() { triggered.bar1 ++ ; } ;
onBar2 = function() { triggered.bar2 ++ ; } ;
// 1 listener for 'foo'
bus.on( 'foo' , onFoo1 ) ;
// 2 listeners for 'bar'
bus.on( 'bar' , onBar1 ) ;
// Same listener added multiple times
bus.on( 'bar' , onBar2 ) ;
bus.on( 'bar' , onBar2 ) ;
bus.on( 'bar' , onBar2 ) ;
bus.emit( 'foo' ) ;
bus.emit( 'bar' ) ;
expect( triggered ).to.eql( { foo1: 1 , bar1: 1 , bar2: 3 } ) ;
bus.removeListener( 'bar' , onBar2 ) ;
bus.emit( 'bar' ) ;
expect( triggered ).to.eql( { foo1: 1 , bar1: 2 , bar2: 3 } ) ;should emit 'newListener' every time a new listener is added, with an array of listener object.
var bus = Object.create( NextGenEvents.prototype ) ;
var stats = { count: {} , orders: [] } ;
bus.on( 'newListener' , genericListener.bind( undefined , 'new1' , stats , function( listeners ) {
expect( listeners.length ).to.be( 1 ) ;
expect( typeof listeners[ 0 ] ).to.be( 'object' ) ;
switch ( stats.count.new1 )
{
case 1 :
expect( listeners[ 0 ].event ).to.be( 'foo' ) ;
break ;
case 2 :
expect( listeners[ 0 ].event ).to.be( 'newListener' ) ;
break ;
case 3 :
expect( listeners[ 0 ].event ).to.be( 'bar' ) ;
break ;
default :
expect().fail() ;
}
} ) ) ;
expect( stats.count ).to.eql( {} ) ;
bus.on( 'foo' , genericListener.bind( undefined , 'foo' , stats , undefined ) ) ;
expect( stats.count ).to.eql( { new1: 1 } ) ;
expect( stats.orders ).to.eql( [ 'new1' ] ) ;
bus.emit( 'foo' ) ;
expect( stats.count ).to.eql( { new1: 1 , foo: 1 } ) ;
expect( stats.orders ).to.eql( [ 'new1' , 'foo' ] ) ;
bus.on( 'newListener' , genericListener.bind( undefined , 'new2' , stats , function( listeners ) {
expect( listeners.length ).to.be( 1 ) ;
expect( typeof listeners[ 0 ] ).to.be( 'object' ) ;
switch ( stats.count.new2 )
{
case 1 :
expect( listeners[ 0 ].event ).to.be( 'bar' ) ;
break ;
default :
expect().fail() ;
}
} ) ) ;
expect( stats.count ).to.eql( { new1: 2 , foo: 1 } ) ;
expect( stats.orders ).to.eql( [ 'new1' , 'foo' , 'new1' ] ) ;
bus.once( 'bar' , genericListener.bind( undefined , 'bar' , stats , undefined ) ) ;
expect( stats.count ).to.eql( { new1: 3 , new2: 1 , foo: 1 } ) ;
expect( stats.orders ).to.eql( [ 'new1' , 'foo' , 'new1' , 'new1' , 'new2' ] ) ;
bus.emit( 'bar' ) ;
expect( stats.count ).to.eql( { new1: 3 , new2: 1 , foo: 1 , bar: 1 } ) ;
expect( stats.orders ).to.eql( [ 'new1' , 'foo' , 'new1' , 'new1' , 'new2' , 'bar' ] ) ;should emit 'removeListener' every time a new listener is removed (one time listener count as well once triggered), with an array of listener object.
var bus = Object.create( NextGenEvents.prototype ) ;
var stats = { count: {} , orders: [] } ;
var onFoo = genericListener.bind( undefined , 'foo' , stats , undefined ) ;
var onBar1 = genericListener.bind( undefined , 'bar1' , stats , undefined ) ;
var onBar2 = genericListener.bind( undefined , 'bar2' , stats , undefined ) ;
bus.on( 'removeListener' , genericListener.bind( undefined , 'rm1' , stats , function( listeners ) {
switch ( stats.count.rm1 )
{
case 1 :
expect( listeners.length ).to.be( 1 ) ;
expect( typeof listeners[ 0 ] ).to.be( 'object' ) ;
expect( listeners[ 0 ].event ).to.be( 'foo' ) ;
expect( listeners[ 0 ].id ).to.be( onFoo ) ;
break ;
case 2 :
expect( listeners.length ).to.be( 3 ) ;
expect( typeof listeners[ 0 ] ).to.be( 'object' ) ;
expect( typeof listeners[ 1 ] ).to.be( 'object' ) ;
expect( typeof listeners[ 2 ] ).to.be( 'object' ) ;
expect( listeners[ 0 ].event ).to.be( 'foo' ) ;
expect( listeners[ 0 ].id ).to.be( onFoo ) ;
expect( listeners[ 1 ].event ).to.be( 'foo' ) ;
expect( listeners[ 1 ].id ).to.be( onFoo ) ;
expect( listeners[ 2 ].event ).to.be( 'foo' ) ;
expect( listeners[ 2 ].id ).to.be( onFoo ) ;
break ;
case 3 :
expect( listeners.length ).to.be( 1 ) ;
expect( typeof listeners[ 0 ] ).to.be( 'object' ) ;
expect( listeners[ 0 ].event ).to.be( 'foo' ) ;
expect( listeners[ 0 ].id ).to.be( onFoo ) ;
break ;
case 4 :
expect( listeners.length ).to.be( 2 ) ;
expect( typeof listeners[ 0 ] ).to.be( 'object' ) ;
expect( typeof listeners[ 1 ] ).to.be( 'object' ) ;
expect( listeners[ 0 ].event ).to.be( 'bar' ) ;
expect( listeners[ 0 ].id ).to.be( onBar1 ) ;
expect( listeners[ 1 ].event ).to.be( 'bar' ) ;
expect( listeners[ 1 ].id ).to.be( onBar2 ) ;
break ;
default :
expect().fail() ;
}
} ) ) ;
expect( stats.count ).to.eql( {} ) ;
bus.on( 'foo' , onFoo ) ;
expect( stats.count ).to.eql( {} ) ;
expect( stats.orders ).to.eql( [] ) ;
bus.off( 'foo' , onFoo ) ;
expect( stats.count ).to.eql( { rm1: 1 } ) ;
expect( stats.orders ).to.eql( [ 'rm1' ] ) ;
bus.on( 'foo' , onFoo ) ;
bus.on( 'foo' , onFoo ) ;
bus.on( 'foo' , onFoo ) ;
expect( stats.count ).to.eql( { rm1: 1 } ) ;
expect( stats.orders ).to.eql( [ 'rm1' ] ) ;
bus.off( 'foo' , onFoo ) ;
expect( stats.count ).to.eql( { rm1: 2 } ) ;
expect( stats.orders ).to.eql( [ 'rm1' , 'rm1' ] ) ;
bus.once( 'foo' , onFoo ) ;
expect( stats.count ).to.eql( { rm1: 2 } ) ;
expect( stats.orders ).to.eql( [ 'rm1' , 'rm1' ] ) ;
bus.emit( 'foo' , onFoo ) ;
expect( stats.count ).to.eql( { rm1: 3 , foo: 1 } ) ;
expect( stats.orders ).to.eql( [ 'rm1' , 'rm1' , 'foo' , 'rm1' ] ) ;
bus.on( 'foo' , onFoo ) ;
bus.on( 'bar' , onBar1 ) ;
bus.on( 'bar' , onBar2 ) ;
bus.removeAllListeners( 'bar' ) ;
expect( stats.count ).to.eql( { rm1: 4 , foo: 1 } ) ;
expect( stats.orders ).to.eql( [ 'rm1' , 'rm1' , 'foo' , 'rm1' , 'rm1' ] ) ;
bus.on( 'foo' , onFoo ) ;
bus.on( 'bar' , onBar1 ) ;
bus.on( 'bar' , onBar2 ) ;
bus.removeAllListeners() ;
// 'removeListener' listener are not fired: they are already deleted
expect( stats.count ).to.eql( { rm1: 4 , foo: 1 } ) ;
expect( stats.orders ).to.eql( [ 'rm1' , 'rm1' , 'foo' , 'rm1' , 'rm1' ] ) ;.listeners() should return all the listeners for an event.
var bus = Object.create( NextGenEvents.prototype ) ;
var listeners , onFoo1 ;
onFoo1 = function() {} ;
bus.on( 'foo' , onFoo1 ) ;
listeners = bus.listeners( 'foo' ) ;
expect( listeners.length ).to.be( 1 ) ;
expect( listeners[ 0 ].id ).to.be( onFoo1 ) ;
expect( listeners[ 0 ].fn ).to.be( onFoo1 ) ;
expect( listeners[ 0 ].event ).to.be( 'foo' ) ;
expect( bus.listeners( 'bar' ).length ).to.be( 0 ) ;
bus.on( 'foo' , onFoo1 ) ;
bus.on( 'foo' , onFoo1 ) ;
listeners = bus.listeners( 'foo' ) ;
expect( listeners.length ).to.be( 3 ) ;
expect( listeners[ 1 ].id ).to.be( onFoo1 ) ;
expect( listeners[ 1 ].fn ).to.be( onFoo1 ) ;
expect( listeners[ 1 ].event ).to.be( 'foo' ) ;
expect( listeners[ 2 ].id ).to.be( onFoo1 ) ;
expect( listeners[ 2 ].fn ).to.be( onFoo1 ) ;
expect( listeners[ 2 ].event ).to.be( 'foo' ) ;
expect( bus.listeners( 'bar' ).length ).to.be( 0 ) ;
bus.removeListener( 'foo' , onFoo1 ) ;
expect( bus.listeners( 'foo' ).length ).to.be( 0 ) ;
expect( bus.listeners( 'bar' ).length ).to.be( 0 ) ;
bus.once( 'foo' , onFoo1 ) ;
listeners = bus.listeners( 'foo' ) ;
expect( listeners.length ).to.be( 1 ) ;
expect( listeners[ 0 ].id ).to.be( onFoo1 ) ;
expect( listeners[ 0 ].fn ).to.be( onFoo1 ) ;
expect( listeners[ 0 ].event ).to.be( 'foo' ) ;
expect( bus.listeners( 'bar' ).length ).to.be( 0 ) ;
bus.emit( 'foo' ) ;
listeners = bus.listeners( 'foo' ) ;
expect( bus.listeners( 'foo' ).length ).to.be( 0 ) ;
expect( bus.listeners( 'bar' ).length ).to.be( 0 ) ;Next Gen feature: async emitting
should emit synchronously, with a synchronous flow (nice = NextGenEvents.SYNC).
asyncEventTest( NextGenEvents.SYNC , undefined , undefined , undefined , function( order ) {
expect( order ).to.eql( [ 'listener' , 'flow' , 'nextTick' , 'setImmediate' , 'setTimeout5' , 'setTimeout20' ] ) ;
done() ;
} ) ;should emit asynchronously, with an asynchronous flow, as fast as possible (nice = NextGenEvents.NEXT_TICK).
asyncEventTest( NextGenEvents.NEXT_TICK , undefined , undefined , undefined , function( order ) {
expect( order ).to.eql( [ 'flow' , 'listener' , 'nextTick' , 'setImmediate' , 'setTimeout5' , 'setTimeout20' ] ) ;
done() ;
} ) ;should emit asynchronously, with an asynchronous flow, almost as fast as possible (nice = NextGenEvents.IMMEDIATE).
asyncEventTest( NextGenEvents.IMMEDIATE , undefined , undefined , undefined , function( order ) {
expect( order ).to.eql( [ 'flow' , 'nextTick' , 'listener' , 'setImmediate' , 'setTimeout5' , 'setTimeout20' ] ) ;
done() ;
} ) ;should emit asynchronously, with an asynchronous flow, with minimal delay (nice = NextGenEvents.TIMEOUT).
asyncEventTest( NextGenEvents.TIMEOUT , undefined , undefined , undefined , function( order ) {
try {
expect( order ).to.eql( [ 'flow' , 'nextTick' , 'setImmediate' , 'listener' , 'setTimeout5' , 'setTimeout20' ] ) ;
}
catch( error ) {
// Sometime setImmediate() is unpredictable and is slower than setTimeout(fn,0)
// It is a bug of V8, not a bug of the async lib
expect( order ).to.eql( [ 'flow' , 'nextTick' , 'listener' , 'setImmediate' , 'setTimeout5' , 'setTimeout20' ] ) ;
}
done() ;
} ) ;should emit asynchronously, with an asynchronous flow, with a 10ms delay (nice = 1 -> setTimeout 10ms).
asyncEventTest( 1 , undefined , undefined , undefined , function( order ) {
expect( order ).to.eql( [ 'flow' , 'nextTick' , 'setImmediate' , 'setTimeout5' , 'listener' , 'setTimeout20' ] ) ;
done() ;
} ) ;should emit asynchronously, with an asynchronous flow, with a 30ms delay (nice = 3 -> setTimeout 30ms).
asyncEventTest( 3 , undefined , undefined , undefined , function( order ) {
expect( order ).to.eql( [ 'flow' , 'nextTick' , 'setImmediate' , 'setTimeout5' , 'setTimeout20' , 'listener' ] ) ;
done() ;
} ) ;.emit( nice , event , ... ) should overide emitter's nice value.
asyncEventTest( undefined , 1 , undefined , undefined , function( order ) {
expect( order ).to.eql( [ 'flow' , 'nextTick' , 'setImmediate' , 'setTimeout5' , 'listener' , 'setTimeout20' ] ) ;
asyncEventTest( NextGenEvents.SYNC , 1 , undefined , undefined , function( order ) {
expect( order ).to.eql( [ 'flow' , 'nextTick' , 'setImmediate' , 'setTimeout5' , 'listener' , 'setTimeout20' ] ) ;
asyncEventTest( 10 , 1 , undefined , undefined , function( order ) {
expect( order ).to.eql( [ 'flow' , 'nextTick' , 'setImmediate' , 'setTimeout5' , 'listener' , 'setTimeout20' ] ) ;
done() ;
} ) ;
} ) ;
} ) ;should use the highest nice value between the context's nice, the listener's nice and the emitter's nice.
asyncEventTest( undefined , 1 , NextGenEvents.SYNC , NextGenEvents.SYNC , function( order ) {
expect( order ).to.eql( [ 'flow' , 'nextTick' , 'setImmediate' , 'setTimeout5' , 'listener' , 'setTimeout20' ] ) ;
asyncEventTest( undefined , NextGenEvents.SYNC , 1 , NextGenEvents.SYNC , function( order ) {
expect( order ).to.eql( [ 'flow' , 'nextTick' , 'setImmediate' , 'setTimeout5' , 'listener' , 'setTimeout20' ] ) ;
asyncEventTest( undefined , NextGenEvents.SYNC , NextGenEvents.SYNC , 1 , function( order ) {
expect( order ).to.eql( [ 'flow' , 'nextTick' , 'setImmediate' , 'setTimeout5' , 'listener' , 'setTimeout20' ] ) ;
done() ;
} ) ;
} ) ;
} ) ;Next Gen feature: contexts
when a listener is tied to a context, it should stop receiving events if the context is disabled (implicit context declaration).
var bus = Object.create( NextGenEvents.prototype ) ;
var triggered = 0 ;
bus.on( 'foo' , {
context: 'bar' ,
fn: function() { triggered ++ ; }
} ) ;
bus.emit( 'foo' ) ;
expect( triggered ).to.be( 1 ) ;
bus.disableListenerContext( 'bar' ) ;
bus.emit( 'foo' ) ;
bus.emit( 'foo' ) ;
bus.emit( 'foo' ) ;
expect( triggered ).to.be( 1 ) ;
bus.enableListenerContext( 'bar' ) ;
bus.emit( 'foo' ) ;
expect( triggered ).to.be( 2 ) ;when a listener is tied to a context, it should stop receiving events if the context is disabled (explicit context declaration).
var bus = Object.create( NextGenEvents.prototype ) ;
var triggered = 0 ;
bus.addListenerContext( 'bar' , { status: NextGenEvents.CONTEXT_DISABLED } ) ;
bus.on( 'foo' , {
context: 'bar' ,
fn: function() { triggered ++ ; }
} ) ;
bus.emit( 'foo' ) ;
bus.emit( 'foo' ) ;
bus.emit( 'foo' ) ;
expect( triggered ).to.be( 0 ) ;
bus.enableListenerContext( 'bar' ) ;
bus.emit( 'foo' ) ;
expect( triggered ).to.be( 1 ) ;
bus.disableListenerContext( 'bar' ) ;
bus.emit( 'foo' ) ;
expect( triggered ).to.be( 1 ) ;
bus.enableListenerContext( 'bar' ) ;
bus.emit( 'foo' ) ;
expect( triggered ).to.be( 2 ) ;.destroyListenerContext() should destroy a context and all listeners tied to it.
var bus = Object.create( NextGenEvents.prototype ) ;
var stats = { count: {} , orders: [] } ;
bus.on( 'foo' , {
id: 'foo1' ,
context: 'bar' ,
fn: genericListener.bind( undefined , 'foo1' , stats , undefined )
} ) ;
bus.on( 'foo' , {
id: 'foo2' ,
context: 'bar' ,
fn: genericListener.bind( undefined , 'foo2' , stats , undefined )
} ) ;
bus.on( 'baz' , {
id: 'baz1' ,
context: 'bar' ,
fn: genericListener.bind( undefined , 'baz1' , stats , undefined )
} ) ;
bus.on( 'baz' , {
id: 'baz2' ,
context: 'qux' ,
fn: genericListener.bind( undefined , 'baz2' , stats , undefined )
} ) ;
bus.emit( 'foo' ) ;
expect( stats.count ).to.eql( { foo1: 1 , foo2: 1 } ) ;
bus.emit( 'baz' ) ;
expect( stats.count ).to.eql( { foo1: 1 , foo2: 1 , baz1: 1 , baz2: 1 } ) ;
bus.destroyListenerContext( 'bar' ) ;
bus.emit( 'foo' ) ;
expect( stats.count ).to.eql( { foo1: 1 , foo2: 1 , baz1: 1 , baz2: 1 } ) ;
bus.emit( 'baz' ) ;
expect( stats.count ).to.eql( { foo1: 1 , foo2: 1 , baz1: 1 , baz2: 2 } ) ;
bus.destroyListenerContext( 'qux' ) ;
bus.emit( 'foo' ) ;
expect( stats.count ).to.eql( { foo1: 1 , foo2: 1 , baz1: 1 , baz2: 2 } ) ;
bus.emit( 'baz' ) ;
expect( stats.count ).to.eql( { foo1: 1 , foo2: 1 , baz1: 1 , baz2: 2 } ) ;Next Gen feature: contexts queue
.queueListenerContext() should pause the context, queueing events, .enableListenerContext() should resume pending events emitting.
var bus = Object.create( NextGenEvents.prototype ) ;
var stats = { count: {} , orders: [] } ;
bus.on( 'foo' , {
id: 'foobar' ,
context: 'qux' ,
fn: genericListener.bind( undefined , 'foobar' , stats , function() {
var args = Array.prototype.slice.call( arguments ) ;
switch ( stats.count.foobar )
{
case 1 :
expect( args ).to.eql( [ 'one' , 'two' , 'three' ] ) ;
break ;
case 2 :
expect( args ).to.eql( [ 'four' , 'five' , 'six' ] ) ;
break ;
case 3 :
expect( args ).to.eql( [] ) ;
break ;
case 4 :
expect( args ).to.eql( [ 'seven' ] ) ;
break ;
}
} )
} ) ;
bus.on( 'foo' , {
id: 'foobaz' ,
context: 'qux' ,
fn: genericListener.bind( undefined , 'foobaz' , stats , function() {
var args = Array.prototype.slice.call( arguments ) ;
switch ( stats.count.foobaz )
{
case 1 :
expect( args ).to.eql( [ 'one' , 'two' , 'three' ] ) ;
break ;
case 2 :
expect( args ).to.eql( [ 'four' , 'five' , 'six' ] ) ;
break ;
case 3 :
expect( args ).to.eql( [] ) ;
break ;
case 4 :
expect( args ).to.eql( [ 'seven' ] ) ;
break ;
}
} )
} ) ;
bus.on( 'qbar' , {
id: 'qbarbaz' ,
context: 'qbarbaz' ,
fn: genericListener.bind( undefined , 'qbarbaz' , stats , undefined )
} ) ;
bus.emit( 'foo' , 'one' , 'two' , 'three' ) ;
bus.emit( 'qbar' ) ;
expect( stats.count ).to.eql( { foobar: 1 , foobaz: 1 , qbarbaz: 1 } ) ;
bus.queueListenerContext( 'qux' ) ;
bus.emit( 'foo' , 'four' , 'five' , 'six' ) ;
bus.emit( 'foo' ) ;
bus.emit( 'foo' , 'seven' ) ;
bus.emit( 'qbar' ) ;
expect( stats.count ).to.eql( { foobar: 1 , foobaz: 1 , qbarbaz: 2 } ) ;
bus.enableListenerContext( 'qux' ) ;
expect( stats.count ).to.eql( { foobar: 4 , foobaz: 4 , qbarbaz: 2 } ) ;Next Gen feature: contexts serialization
3 async listeners for an event, tied to a serial context, each listener should be triggered one after the other.
var bus = Object.create( NextGenEvents.prototype ) ;
var stats = { count: {} , orders: [] } ;
bus.on( 'foo' , {
id: 'foobar' ,
context: 'qux' ,
async: true ,
fn: genericListener.bind( undefined , 'foobar' , stats , function() {
var callback = arguments[ arguments.length - 1 ] ;
setTimeout( callback , 30 ) ;
} )
} ) ;
bus.on( 'foo' , {
id: 'foobaz' ,
context: 'qux' ,
async: true ,
fn: genericListener.bind( undefined , 'foobaz' , stats , function() {
expect( stats.count ).to.eql( { foobar: 1 , foobaz: 1 } ) ;
var callback = arguments[ arguments.length - 1 ] ;
setTimeout( callback , 30 ) ;
} )
} ) ;
bus.on( 'foo' , {
id: 'foobarbaz' ,
context: 'qux' ,
async: true ,
fn: genericListener.bind( undefined , 'foobarbaz' , stats , function() {
expect( stats.count ).to.eql( { foobar: 1 , foobaz: 1 , foobarbaz: 1 } ) ;
var callback = arguments[ arguments.length - 1 ] ;
setTimeout( function() {
callback() ;
done() ;
} , 30 ) ;
} )
} ) ;
bus.serializeListenerContext( 'qux' ) ;
bus.emit( 'foo' ) ;
expect( stats.count ).to.eql( { foobar: 1 } ) ;3 async listeners for 3 events, tied to a serial context, each listener should be triggered one after the other.
var bus = Object.create( NextGenEvents.prototype ) ;
var stats = { count: {} , orders: [] } ;
bus.on( 'bar' , {
id: 'foobar' ,
context: 'qux' ,
async: true ,
fn: genericListener.bind( undefined , 'foobar' , stats , function() {
var callback = arguments[ arguments.length - 1 ] ;
setTimeout( callback , 30 ) ;
} )
} ) ;
bus.on( 'baz' , {
id: 'foobaz' ,
context: 'qux' ,
async: true ,
fn: genericListener.bind( undefined , 'foobaz' , stats , function() {
expect( stats.count ).to.eql( { foobar: 1 , foobaz: 1 } ) ;
var callback = arguments[ arguments.length - 1 ] ;
setTimeout( callback , 30 ) ;
} )
} ) ;
bus.on( 'barbaz' , {
id: 'foobarbaz' ,
context: 'qux' ,
async: true ,
fn: genericListener.bind( undefined , 'foobarbaz' , stats , function() {
expect( stats.count ).to.eql( { foobar: 1 , foobaz: 1 , foobarbaz: 1 } ) ;
var callback = arguments[ arguments.length - 1 ] ;
setTimeout( function() {
callback() ;
done() ;
} , 30 ) ;
} )
} ) ;
bus.serializeListenerContext( 'qux' ) ;
bus.emit( 'bar' ) ;
bus.emit( 'baz' ) ;
bus.emit( 'barbaz' ) ;
expect( stats.count ).to.eql( { foobar: 1 } ) ;mixing sync and async listeners tied to a serial context, sync event should not block (test 1).
var bus = Object.create( NextGenEvents.prototype ) ;
var stats = { count: {} , orders: [] } ;
bus.on( 'bar' , {
id: 'foobar' ,
context: 'qux' ,
fn: genericListener.bind( undefined , 'foobar' , stats , function() {
} )
} ) ;
bus.on( 'baz' , {
id: 'foobaz' ,
context: 'qux' ,
fn: genericListener.bind( undefined , 'foobaz' , stats , function() {
} )
} ) ;
bus.on( 'barbaz' , {
id: 'foobarbaz' ,
context: 'qux' ,
async: true ,
fn: genericListener.bind( undefined , 'foobarbaz' , stats , function() {
expect( stats.count ).to.eql( { foobar: 1 , foobaz: 1 , foobarbaz: 1 } ) ;
var callback = arguments[ arguments.length - 1 ] ;
setTimeout( function() {
callback() ;
done() ;
} , 30 ) ;
} )
} ) ;
bus.serializeListenerContext( 'qux' ) ;
bus.emit( 'bar' ) ;
bus.emit( 'baz' ) ;
bus.emit( 'barbaz' ) ;
expect( stats.count ).to.eql( { foobar: 1 , foobaz: 1 , foobarbaz: 1 } ) ;mixing sync and async listeners tied to a serial context, sync event should not block (test 2).
var bus = Object.create( NextGenEvents.prototype ) ;
var stats = { count: {} , orders: [] } ;
bus.on( 'bar' , {
id: 'foobar' ,
context: 'qux' ,
fn: genericListener.bind( undefined , 'foobar' , stats , function() {
} )
} ) ;
bus.on( 'baz' , {
id: 'foobaz' ,
context: 'qux' ,
async: true ,
fn: genericListener.bind( undefined , 'foobaz' , stats , function() {
expect( stats.count ).to.eql( { foobar: 1 , foobaz: 1 } ) ;
var callback = arguments[ arguments.length - 1 ] ;
setTimeout( callback , 30 ) ;
} )
} ) ;
bus.on( 'barbaz' , {
id: 'foobarbaz' ,
context: 'qux' ,
async: true ,
fn: genericListener.bind( undefined , 'foobarbaz' , stats , function() {
expect( stats.count ).to.eql( { foobar: 1 , foobaz: 1 , foobarbaz: 1 } ) ;
var callback = arguments[ arguments.length - 1 ] ;
setTimeout( function() {
callback() ;
done() ;
} , 30 ) ;
} )
} ) ;
bus.serializeListenerContext( 'qux' ) ;
bus.emit( 'bar' ) ;
bus.emit( 'baz' ) ;
bus.emit( 'barbaz' ) ;
expect( stats.count ).to.eql( { foobar: 1 , foobaz: 1 } ) ;mixing sync and async listeners tied to a serial context, sync event should not block (test 3).
var bus = Object.create( NextGenEvents.prototype ) ;
var stats = { count: {} , orders: [] } ;
bus.on( 'bar' , {
id: 'foobar' ,
context: 'qux' ,
async: true ,
fn: genericListener.bind( undefined , 'foobar' , stats , function() {
var callback = arguments[ arguments.length - 1 ] ;
setTimeout( callback , 30 ) ;
} )
} ) ;
bus.on( 'baz' , {
id: 'foobaz' ,
context: 'qux' ,
fn: genericListener.bind( undefined , 'foobaz' , stats , function() {
expect( stats.count ).to.eql( { foobar: 1 , foobaz: 1 } ) ;
// 'barbaz' should trigger immediately
process.nextTick( function() {
expect( stats.count ).to.eql( { foobar: 1 , foobaz: 1 , foobarbaz: 1 } ) ;
} ) ;
} )
} ) ;
bus.on( 'barbaz' , {
id: 'foobarbaz' ,
context: 'qux' ,
async: true ,
fn: genericListener.bind( undefined , 'foobarbaz' , stats , function() {
expect( stats.count ).to.eql( { foobar: 1 , foobaz: 1 , foobarbaz: 1 } ) ;
var callback = arguments[ arguments.length - 1 ] ;
setTimeout( function() {
callback() ;
done() ;
} , 30 ) ;
} )
} ) ;
bus.serializeListenerContext( 'qux' ) ;
bus.emit( 'bar' ) ;
bus.emit( 'baz' ) ;
bus.emit( 'barbaz' ) ;
expect( stats.count ).to.eql( { foobar: 1 } ) ;