Skip to content
On this page

手写发布订阅模式

js
class EventEmitter {
    constructor() {
        this.events= {}
    }
    //事件订阅,需要接收订阅事件名和对应的回调函数
    on(eventName, callback) {
        if(!this.events[eventName]) {
            this.events[eventName] = []
        }
        this.events[eventName].push(callback)
    }
    //移除订阅,需要移除的订阅事件名及指定的回调函数
    off(eventName, callback) {
        if(this.events[eventName]) {
            // indexOf 与 findIndex的区别
            // indexOf 根据元素值查找对应索引
            // findIndex 参数是一个查询函数,可以自定义查询条件,返回满足条件的元素索引
            const index = this.events[eventName].indexOf(callback)
            if(index !== -1) {
                // 移除指定订阅事件的回调函数
                this.events[eventName].splice(index, 1)
            }
        }
    }
    //事件发布,需要接收发布事件名和对应的参数
    emit(eventName, once = false, ...args) {
        if(this.events[eventName]) {
            // 创建副本,如果回调函数内继续注册相同事件,会造成死循环
            const tasks = this.events[eventName].slice()
            tasks.forEach((callback)=>callback(...args))
            if(once) {
                delete this.events[eventName]
            }
        }
    }
}

// test
const eventBus = new EventEmitter()
const task1 = () => { console.log('task1')}
const task2 = () => { console.log('task2')}

eventBus.on('task', task1)
eventBus.on('task', task2)
eventBus.off('task', task1)

setTimeout(() => {
  eventBus.emit('task') // task2
}, 1000)

Released under the MIT License.