162 lines
4.4 KiB
JavaScript
162 lines
4.4 KiB
JavaScript
// 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)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|