JavaScript设计模式之发布订阅模式

发布订阅模式(Subscribe/Publish)。发布者和订阅者都通过订阅中心进行事件处理。

发布订阅模式主要分为三个阶段订阅on, 发布emit, 退订off

发布订阅模式是依赖函数回调实现的

发布订阅模式的好处

  1. 可复用,扩展性强
  2. 可以让事件跟当前逻辑充分解耦,适合组件间的事件调用和数据传递
  3. 灵活性比较高

如何理解发布订阅模式

我想去篮球场打打球结果到篮球场时,篮球场管理员告诉我现在正在进行设备检修,什么时候能修好还不知道。
如果我想进去这个篮球场打球怎么办?
第一:每过一段时间过来看一下(轮询)
第二:把我的手机号码留给篮球场管理员,球场修好之后给我打电话(发布订阅模式)

结合上面的文字用代码实现

  1. 创建一个篮球场(Observe),并且在篮球场中创建一个对象eventObj(存储电话号码k和要做的事情)
const Observe = function() {
    this.eventObj = {}; // 
};
  1. 创建一个on方法,在eventObj中存储key(电话号码)以及对应的回调函数 -- 订阅
Observe.prototype.on = function(ev, cb) {
    this.eventObj[ev] = cb;
};
  1. 创建一个emit方法,当篮球场修好之后,找到我的电话并且执行回调函数 -- 发布
Observe.prototype.emit = function(ev) {
  if (this.eventObj[ev]) {
    for (const key in this.eventObj) {
      if (key === ev) {
        let args = [];
        for(let i = 1; i<arguments.length; i++) {
          args[i - 1] = arguments[i]
        }
        this.eventObj[ev].apply(this, args)
      }
    }  
  }
};
  1. 移除消息 -- 退订
EventEmitter.prototype.off = function(ev, cb) {
  this.eventObj[ev] = null
};
  1. 实际使用
let Event = new Observe(); //

Event.on('handleCall', str => console.log(str))

Event.emit('handleCell', '篮球场修好了,可以过来打篮球了')

Event.off('handleCell') // 取消订阅

完整代码

const Observe = function() {
    this.eventObj = {};
};

Observe.prototype.on = function(ev, cb) {
    this.eventObj[ev] = [];
    this.eventObj[ev].push(cb);
    return this;
};
// 执行一次之后就销毁
Observe.prototype.once = function(ev, cb) {
    let self = this;
    let fn = function() {
        self.off(ev, fn);
        let args = [];
        for(let i =0; i<arguments.length; i++) {
            args[i] = arguments[i]
        }
        cb.apply(self, args);
    };
    return this.on(ev, fn);
};

Observe.prototype.emit = function(ev) {
    for (const key in this.eventObj) {
        if (key === ev) {
            if (this.eventObj[ev]) {
                const cbs = this.eventObj[ev] || [];
                for (let i = 0 ; i < cbs.length; i++) {
                    let args = [];
                    for(let i = 1; i<arguments.length; i++) {
                        args[i - 1] = arguments[i]
                    }
                    cbs[i].apply(this, args);
                }
            }
        }
    }
    return this;
};
// 注销观察者
Observe.prototype.off = function(ev, cb) {
    if (arguments.length === 0) {
        this.eventObj = {};
        return this;
    }

    const cbs = this.eventObj[ev];
    if (!cbs) {
        return this;
    }

    if (arguments.length === 1) {
        this.eventObj[ev] = null;
    } else {
        cbs.map((item, i) => {
            if (item === cb) {
                cbs.splice(i, 1);
                return this;
            }
        });
    }
    return this;
};
export default Observe;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容