async-events
Advanced tools
Comparing version 0.1.2 to 0.2.0
/* | ||
* async-events.js: Asynchronous Event Emitter for Node.js | ||
* | ||
* (C) 2011 Tristan Slominski <tristan.slominski@gmail.com> | ||
* (C) 2011-2012 Tristan Slominski <tristan.slominski@gmail.com> | ||
* | ||
@@ -10,4 +10,67 @@ */ | ||
var AsyncEventEmitter = exports.AsyncEventEmitter = function () {}; | ||
var AsyncEventEmitter = exports.AsyncEventEmitter = function ( options ) { | ||
var self = this; | ||
// | ||
// allow for specifying how many events to process with each tick | ||
// this is to allow compensation for the around 160x overhead of | ||
// process.nextTick | ||
// see: https://groups.google.com/d/msg/nodejs/PErl27A4e-A/Vci6T4pGfckJ | ||
// benchmark: https://gist.github.com/1512111 | ||
// | ||
self.__eventsPerTick = options ? options.eventsPerTick : false || 1; | ||
self.__eventsPerTick++; | ||
self.__eventsPerTickCount = self.__eventsPerTick; | ||
self.__dispatchQueued = false; | ||
self.__eventsQueue = []; | ||
self.__waitForNextTick = false; | ||
}; // AsyncEventEmitter | ||
AsyncEventEmitter.prototype.dispatch = function () { | ||
var self = this, | ||
numOfEventsToDispatch; | ||
numOfEventsToDispatch = self.__eventsQueue.length < self.__eventsPerTick ? | ||
self.__eventsQueue.length : self.__eventsPerTick - 1; | ||
for ( var i = 0; i < numOfEventsToDispatch; i++ ) { | ||
var event = self.__eventsQueue.shift(); | ||
--self.__eventsPerTickCount; // decrement available events per tick | ||
switch ( event[ 0 ] ) { | ||
case 'fast1': | ||
event[ 1 ].call( self ); | ||
break; | ||
case 'fast2': | ||
event[ 1 ].call( self, event[ 2 ] ); | ||
break; | ||
case 'fast3': | ||
event[ 1 ].call( self, event[ 2 ], event[ 3 ] ); | ||
break; | ||
case 'slow': | ||
event[ 1 ].apply( self, event[ 2 ] ); | ||
break; | ||
} // switch event.length | ||
} // for i < numOfEventsToDispatch | ||
if ( self.__eventsQueue.length > 0 ) | ||
self.queueDispatch(); | ||
}; // dispatch | ||
AsyncEventEmitter.prototype.emit = function () { | ||
@@ -42,5 +105,11 @@ | ||
if ( ! handler ) return false; // no listeners | ||
if ( typeof handler === 'function' ) { | ||
// determine if we will handle the event now or wait until next tick | ||
if ( ! self.__waitForNextTick && ! --self.__eventsPerTickCount ) { | ||
self.__waitForNextTick = true; | ||
self.__eventsPerTickCount = self.__eventsPerTick; | ||
} | ||
switch ( arguments.length ) { | ||
@@ -50,5 +119,8 @@ // fast cases | ||
process.nextTick( function () { | ||
if ( ! self.__waitForNextTick ) { | ||
handler.call( self ); | ||
}); // nextTick | ||
} else { | ||
self.__eventsQueue.push( [ 'fast1', handler ] ); | ||
self.queueDispatch(); | ||
} // else | ||
break; | ||
@@ -60,5 +132,8 @@ | ||
process.nextTick( function () { | ||
if ( ! self.__waitForNextTick ) { | ||
handler.call( self, arguments1 ); | ||
}); | ||
} else { | ||
self.__eventsQueue.push( [ 'fast2', handler, arguments1 ] ); | ||
self.queueDispatch(); | ||
} // else | ||
break; | ||
@@ -71,5 +146,8 @@ | ||
process.nextTick( function () { | ||
if ( ! self.__waitForNextTick ) { | ||
handler.call( self, arguments1, arguments2 ); | ||
}); // nextTick | ||
} else { | ||
self.__eventsQueue.push( [ 'fast3', handler, arguments1, arguments2 ] ); | ||
self.queueDispatch(); | ||
} // else | ||
break; | ||
@@ -84,5 +162,9 @@ | ||
process.nextTick( function () { | ||
handler.apply( self, args ); | ||
}); | ||
if ( ! self.__waitForNextTick ) { | ||
handler.apply( self, args ); | ||
} else { | ||
self.__eventsQueue.push( [ 'slow', handler, args ] ); | ||
self.queueDispatch(); | ||
} // else | ||
break; | ||
@@ -103,5 +185,14 @@ } // switch arguments.length | ||
process.nextTick( function () { | ||
// determine if we will handle the event now or wait until next tick | ||
if ( ! self.__waitForNextTick && ! --self.__eventsPerTickCount ) { | ||
self.__waitForNextTick = true; | ||
self.__eventsPerTickCount = self.__eventsPerTick; | ||
} | ||
if ( ! self.__waitForNextTick ) { | ||
listeners[ i ].apply( self, args ); | ||
}); | ||
} else { | ||
self.__eventsQueue.push( [ 'slow', listeners[ i ], args ] ); | ||
self.queueDispatch(); | ||
} // else | ||
@@ -159,2 +250,19 @@ } // for i in listeners.length | ||
AsyncEventEmitter.prototype.queueDispatch = function () { | ||
var self = this; | ||
if ( ! self.__dispatchQueued ) { | ||
self.__dispatchQueued = true; | ||
process.nextTick( function () { | ||
self.__dispatchQueued = false; | ||
self.dispatch(); | ||
}); | ||
} // if ! self.__dispatchQueued | ||
}; // queueDispatch | ||
AsyncEventEmitter.prototype.removeListener = function ( type, listener ) { | ||
@@ -161,0 +269,0 @@ |
{ | ||
"name" : "async-events", | ||
"description" : "An asynchronous Node.js event emitter implementation.", | ||
"version" : "0.1.2", | ||
"version" : "0.2.0", | ||
"author" : "Tristan Slominski <tristan.slominski@gmail.com>", | ||
"main" : "./lib/async-events.js", | ||
"engines" : { | ||
"node" : ">=0.4.x" | ||
"node" : "0.6.x" | ||
} | ||
} |
@@ -28,3 +28,3 @@ # AsyncEventEmitter | ||
Copyright (c) 2011 Tristan Slominski <tristan.slominski@gmail.com> | ||
Copyright (c) 2011-2012 Tristan Slominski <tristan.slominski@gmail.com> | ||
@@ -31,0 +31,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: |
13700
304