Skip to content

设计模式之发布订阅模式

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)