Last active
September 25, 2019 06:00
-
-
Save xincici/e64d79e0a77c14c90794cb9fb213f9ec to your computer and use it in GitHub Desktop.
just one simple implementation of NodeJS EventEmitter module
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var assert = require('assert'); | |
var util = require('util'); | |
function on(thisArg, eventName, fn, isOnce, isPrepend) { | |
assert(eventName && typeof fn === 'function', 'Need eventName and callback function'); | |
if (eventName !== 'newListener' || thisArg.listenerCount('newListener')){ | |
thisArg.emit('newListener', eventName, fn); | |
} | |
if (thisArg.fns[eventName]) { | |
if (thisArg.fns[eventName].length < thisArg.getMaxListeners()) { | |
thisArg.fns[eventName][isPrepend ? 'unshift' : 'push']({ | |
fn, | |
isOnce, | |
}); | |
} else { | |
throw new TypeError('maxListeners exceed!'); | |
} | |
} else { | |
thisArg.fns[eventName] = [{ | |
fn, | |
isOnce, | |
}]; | |
} | |
return thisArg; | |
} | |
class Event { | |
constructor() { | |
this.fns = {}; | |
} | |
on(eventName, fn) { | |
return on(this, eventName, fn); | |
} | |
addListener(eventName, fn) { | |
return on(this, eventName, fn); | |
} | |
once(eventName, fn) { | |
return on(this, eventName, fn, true); | |
} | |
prependListener(eventName, fn) { | |
return on(this, eventName, fn, false, true); | |
} | |
prependOnceListener(eventName, fn) { | |
return on(this, eventName, fn, true, true); | |
} | |
emit(eventName, ...args) { | |
var cbs = this.fns[eventName]; | |
if (cbs && cbs.length) { | |
cbs.forEach(cb => { | |
if (cb.isOnce) { | |
this.removeListener(eventName, cb.fn); | |
} | |
cb.fn.apply(this, args); | |
}); | |
return true; | |
} | |
return false; | |
} | |
removeListener(eventName, fn) { | |
var cbs = this.fns[eventName]; | |
if (cbs && cbs.length) { | |
var index = cbs.findIndex(cb => cb.fn === fn); | |
index >= 0 && this.fns[eventName].splice(index, 1); | |
if (this.fns[eventName].length === 0) { | |
delete this.fns[eventName]; | |
} | |
this.emit('removeListener', eventName, fn); | |
} | |
return this; | |
} | |
removeAllListeners(eventName) { | |
if (!eventName) { | |
this.fns = {}; | |
return this; | |
} | |
var eFns = (this.fns[eventName] || []).map(v => v.fn); | |
delete this.fns[eventName]; | |
eFns.forEach(fn => { | |
this.emit('removeListener', eventName, fn); | |
}); | |
return this; | |
} | |
listeners(eventName) { | |
return (this.fns[eventName] || []).map(v => v.fn); | |
} | |
listenerCount(eventName) { | |
return this.fns[eventName] ? this.fns[eventName].length : 0; | |
} | |
eventNames() { | |
return Object.keys(this.fns); | |
} | |
getMaxListeners() { | |
return this.maxListeners || Event.defaultMaxListeners; | |
} | |
setMaxListeners(count) { | |
this.maxListeners = count; | |
return this; | |
} | |
} | |
Event.listenerCount = util.deprecate( | |
(emitter, eventName) => emitter.listenerCount(eventName), | |
'EventEmitter.listenerCount is depreacated, please use emitter.listenerCount instead' | |
); | |
Event.defaultMaxListeners = 10; | |
Event.EventEmitter = Event; | |
module.exports = Event; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment