一个

一个例子 - 看尽并手写JS发布订阅模式

2019-08-03  本文已影响0人  Jason_Zeng

一个系列: 一个例子看尽一个知识点

发布订阅模式,很多地方都用到的一种模式,简单的说就是预定一件事情,时机成熟通知你,比如我们nodejs中的fs的读写文件的流,消息事件的触发等都用到了这种方式了,虽然不是特别难,但是非常实用,实现方式也简单,基本思想就是内部保存了一个对象存储订阅的函数,调用者通过名字来触发函数,订阅多个就按照队列的形式触发,下面就是具体实现

发布订阅源码

// 发布订阅模式
class EventEmitter {
    constructor() {
        // 事件对象,存放订阅的名字和事件
        this.events = {};
    }
    // 订阅事件的方法
    on(eventName,callback) {
       if (!this.events[eventName]) {
           // 注意时数据,一个名字可以订阅多个事件函数
           this.events[eventName] = [callback]
       } else  {
          // 存在则push到指定数组的尾部保存
           this.events[eventName].push(callback)
       }
    }
    // 触发事件的方法
    emit(eventName) {
        // 遍历执行所有订阅的事件
       this.events[eventName] && this.events[eventName].forEach(cb => cb());
    }
    // 移除订阅事件
    removeListener(eventName, callback) {
        if (this.events[eventName]) {
            this.events[eventName] = this.events[eventName].filter(cb => cb != callback)
        }
    }
    // 只执行一次订阅的事件,然后移除
    once(eventName,callback) {
        // 绑定的时fn, 执行的时候会触发fn函数
        let fn = () => {
           callback(); // fn函数中调用原有的callback
           this.removeListener(eventName,fn); // 删除fn, 再次执行的时候之后执行一次
        }
        this.on(eventName,fn)
    }
}

使用方式

let em = new EventEmitter();
let workday = 0;
em.on("work", function() {
    workday++;
    console.log("work everyday");
});

em.once("love", function() {
    console.log("just love you");
});

function makeMoney() {
    console.log("make one million money");
}
em.on("money",makeMoney);

let time = setInterval(() => {
    em.emit("work");
    em.removeListener("money",makeMoney);
    em.emit("money");
    em.emit("love");
    if (workday === 5) {
        console.log("have a rest")
        clearInterval(time);
    }
}, 1);

输出

work everyday
just love you
work everyday
work everyday
work everyday
work everyday
have a rest

所以说工作五天要休息一次,赚一个亿是不可能的,但只能爱一人

上一篇 下一篇

猜你喜欢

热点阅读