设计模式之发布订阅模式
js
class EventEmitter {
constructor() {
this._events = {}
}
on(eventName, callback) {
const cbs = this._events[eventName] || []
cbs.push(callback)
this._events[eventName] = cbs
}
emit(eventName, ...args) {
const cbs = this._events[eventName]
cbs && cbs.forEach(cb => {
cb.call(this, ...args)
})
}
off(eventName, callback) {
const cbs = this._events[eventName]
const newCbs = cbs.filter(cb => cb !== callback)
this._events[eventName] = newCbs
}
once(eventName, callback) {
this.on(eventName, function one(...args) {
callback.call(this, ...args)
this.off(eventName, one)
})
}
}
// test case
const ee = new EventEmitter()
ee.on('test-event', (...args) => {
console.log(args, 'run 1')
console.log(this)
})
function run2(...args) {
console.log(args, 'run 2')
console.log(this)
}
ee.on('test-event', run2)
// ee.off('test-event', run2)
setTimeout(() => {
ee.emit('test-event', 'emit something', true)
}, 1000)
// test once
// 多次emit, 回调函数仅执行一次
ee.once('test-once-event', function testRunOne(...args) {
console.log(args, this, 'run once')
})
setTimeout(() => {
ee.emit('test-once-event', 'emit once event')
}, 1500)
setTimeout(() => {
ee.emit('test-once-event', 'emit once event 2')
}, 2000)