Files

162 lines
4.4 KiB
JavaScript
Raw Permalink Normal View History

// Ported from nanobus 4.5.0 (MIT) — https://github.com/choojs/nanobus
// Event emitter with a '*' wildcard channel and nanotiming instrumentation.
import nanotiming from './timing.js'
import { ok, equal } from './assert.js'
function assertEventName (eventName, method) {
ok(
typeof eventName === 'string' || typeof eventName === 'symbol',
`nanobus.${method}: eventName should be type string or symbol`
)
}
export default class Nanobus {
constructor (name) {
this._name = name || 'nanobus'
this._starListeners = []
this._listeners = {}
}
emit (eventName, ...data) {
assertEventName(eventName, 'emit')
const emitTiming = nanotiming(this._name + "('" + eventName.toString() + "')")
const listeners = this._listeners[eventName]
if (listeners && listeners.length > 0) {
this._emit(this._listeners[eventName], data)
}
if (this._starListeners.length > 0) {
this._emit(this._starListeners, eventName, data, emitTiming.uuid)
}
emitTiming()
return this
}
on (eventName, listener) {
assertEventName(eventName, 'on')
equal(typeof listener, 'function', 'nanobus.on: listener should be type function')
if (eventName === '*') {
this._starListeners.push(listener)
} else {
if (!this._listeners[eventName]) this._listeners[eventName] = []
this._listeners[eventName].push(listener)
}
return this
}
addListener (eventName, listener) {
return this.on(eventName, listener)
}
prependListener (eventName, listener) {
assertEventName(eventName, 'prependListener')
equal(typeof listener, 'function', 'nanobus.prependListener: listener should be type function')
if (eventName === '*') {
this._starListeners.unshift(listener)
} else {
if (!this._listeners[eventName]) this._listeners[eventName] = []
this._listeners[eventName].unshift(listener)
}
return this
}
once (eventName, listener) {
assertEventName(eventName, 'once')
equal(typeof listener, 'function', 'nanobus.once: listener should be type function')
const self = this
this.on(eventName, function once (...args) {
listener.apply(self, args)
self.removeListener(eventName, once)
})
return this
}
prependOnceListener (eventName, listener) {
assertEventName(eventName, 'prependOnceListener')
equal(typeof listener, 'function', 'nanobus.prependOnceListener: listener should be type function')
const self = this
this.prependListener(eventName, function once (...args) {
listener.apply(self, args)
self.removeListener(eventName, once)
})
return this
}
removeListener (eventName, listener) {
assertEventName(eventName, 'removeListener')
equal(typeof listener, 'function', 'nanobus.removeListener: listener should be type function')
if (eventName === '*') {
this._starListeners = this._starListeners.slice()
return remove(this._starListeners, listener)
} else {
if (typeof this._listeners[eventName] !== 'undefined') {
this._listeners[eventName] = this._listeners[eventName].slice()
}
return remove(this._listeners[eventName], listener)
}
function remove (arr, listener) {
if (!arr) return
const index = arr.indexOf(listener)
if (index !== -1) {
arr.splice(index, 1)
return true
}
}
}
removeAllListeners (eventName) {
if (eventName) {
if (eventName === '*') {
this._starListeners = []
} else {
this._listeners[eventName] = []
}
} else {
this._starListeners = []
this._listeners = {}
}
return this
}
listeners (eventName) {
const listeners = eventName !== '*'
? this._listeners[eventName]
: this._starListeners
return listeners ? listeners.slice() : []
}
_emit (arr, eventName, data, uuid) {
if (typeof arr === 'undefined') return
if (arr.length === 0) return
if (data === undefined) {
data = eventName
eventName = null
}
if (eventName) {
if (uuid !== undefined) {
data = [eventName].concat(data, uuid)
} else {
data = [eventName].concat(data)
}
}
// Take a copy in case a listener mutates the array while we iterate.
const listeners = arr.slice()
for (let i = 0; i < listeners.length; i++) {
const listener = listeners[i]
listener.apply(listener, data)
}
}
}