发布-订阅模式

什么是发布-订阅模式?

1、说一下定义噻
发布-订阅模式其实是一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到状态改变的通知。
2、简单的流程
订阅者将自己订阅的事件注册到调度中心,当发布者发布该事件到调度中心,当该事件触发时,由调度中心统一调度订阅者注册到调度中心的处理代码。
3、举个例子吧
我们在微博上关注自己喜欢的爱豆时,爱豆发微博的行为就可以看做是一个简单的发布-订阅模式。我们是订阅者,爱豆是发布者,微博平台是调度中心。当爱豆发送微博到微博平台,平台会将这条微博推送到我们自己的微博上。

如何实现?

1、思路

  • 创建对象(调度中心)
  • on 方法用来把函数都存放在调度中心(订阅这事件注册到调度中心)
  • emit 方法取到arguments里第一个当做event,根据event值去执行调度中心的事件(发布者发布事件到调度中心,调度中心开始处理代码)
  • off 方法可以根据event值取消订阅(取消订阅)
  • once 方法只监听一次,调用完毕后删除缓存函数(订阅一次)
    2、实现
let bus = {
    list: {}, // 调度中心
    on(event, fn) { // 订阅
        let self = this;
        // 存放订阅的事件
        // 该事件存在则直接存放 该事件不存在则开辟数组开始存放
        (self.list[event] || (self.list[event] = [])).push(fn);
        return self;
    },
    once(event, fn) { // 订阅一次
        let self = this;
        function on() {
            self.off(event, on);
            fn.apply(self, arguments);
        }
        on.fn = fn;
        self.on(event, on);
        return self;
    },
    emit(...args) { // 发布
        let self = this;
        // 通过shift拿到事件名称
        let event = args.shift();
        // 通过事件名称拿到对应的存放事件
        let fns = [...self.list[event]];
        if (!fns || (fns.length === 0)) {
            return false;
        }
        fns.forEach(fn => {
            fn.apply(self, args);
        });
        return self;
    },
    off(event, fn) { // 取消订阅
        let self = this;
        let fns = self.list[event];
        if (!fns) {
            return false;
        }
        if (!fn) {
            // 如果没有传递fn 将event对应的缓存列表清空
            fns && (fns.length = 0);
        } else {
            let cb;
            for (let i = 0, i < fns.length; i < length; i++) {
                cb = fns[i];
                if (cb === fn || cb.fn === fn) {
                    fns.split(i, 1);
                }
            }
        }
        return self;
    }
};

小结一下

本来简单的捋了捋思路,有个大概印象,也加深自己对于发布-订阅模式的印象。同时也有一些疑问,对于只订阅一次那里始终存疑,感觉有点绕不明白,我这里也多多思考,也希望大家多多批评指教。

你可能感兴趣的:(发布-订阅模式)