使用JS完成简单事件管理

之前在这篇文章写过,但是当时不理解。其实考察的是设计模式,发布订阅模式,理解后再手动写一次。

总结一下:维护一个对象,属性值为事件名称,值为一个数组,里面存的是所有订阅者的回调函数,emit事件时循环执行数组中的函数,同时查看函数的_once值是否为true,如果是在调用函数后取消监听这个事件。


// 类型: 校招
// 时长: 30 分钟
// 姓名:
// 日期:
// 实现下面的 EventEmitter 类, 用于简单的事件管理.
// 提示:
// 运行代码快捷键: Ctrl + S
class EventEmitter {
    constructor () {
        this.listener = {}
    }
    emit(type, ...args) {
        if (!this.listener.hasOwnProperty(type)) {
            return
        } else {
            this.listener[type].forEach(element => {
                element(...arg)
                if (element._once === true) {
                    this.off(type, element)
                }
            });
        }
    }
    once(type, listener) {
        listener._once = true
        if(!this.listener.hasOwnProperty(type)) {
            this.listener[type] = [listener]
        } else {
            this.listener[type].push(listener)
        }
    }
    on(type, listener) {
        if(!this.listener.hasOwnProperty(type)) {
            this.listener[type] = [listener]
        } else {
            this.listener[type].push(listener)
        }
    }
    off(type, listener) {
        const funcarr = this.listener[type]
        if(funcarr.indexOf(listener) !== -1) {
            funcarr.splice(funcarr.indexOf(listener), 1)
            if(funcarr.length === 0) {
                delete this.listener[type]
            }
        }
    }
}
// 在不修改下面代码的情况下, 能满足下面列举的使用
console.log('输出结果:');
const target = new EventEmitter();
// once
target.once('ready', id => console.log('ready', id));
target.emit('ready', 1);
target.emit('ready', 2);
const messageListener = (...args) => console.log(args);
// on
target.on('message', messageListener);
target.emit('message', 'hello');
target.emit('message', 'world', '!');
// off
target.off('message', messageListener);
target.emit('message', 'nothing');
// 输出结果参考
// 输出结果:
// ready 1
// hello
// world !
// (off 后无输出)

2 评论

  1. 姜辰 2019年05月13日 回复
    技术流,好久不见哈
    1. Curtion [博主] 2019年05月14日 回复
      回复 姜辰: 靠这个恰饭嘛,还是老师好玩