发布订阅模式,求轻拍

389 阅读2分钟

什么是发布订阅模式?

从字面意思来讲,分为发布和订阅两个过程。

  1. 发布:就是事件发生的过程,比如发布了一个新闻,发布了一篇文章。
  2. 订阅:就是接受到发布的事件之后做的事情,比如你订阅了我的微信公众号,我发布一篇文章,你接受到了,然后打开了,点了个赞(做的事情)。

实际上,我们平常使用中,是先订阅,再发布这样的过程,如果没有订阅,发布有啥意义嘛。。

有啥用?

我个人理解就是解耦,将发布和订阅这两个过程分离开。

放“码”过来

function Event () {
  this.evnets = {};
}
Event.prototype.on = function (eventName, callback) {
  this.evnets[eventName] = callback;
}
Event.prototype.emit = function (eventName, args) {
  this.evnets[eventName].handler(args);
}

打完收工。

优化一下,增加off和once方法。

function Event () {
  this.evnets = {};
}
Event.prototype.on = function (eventName, callback) {
  this.evnets[eventName] = {
    once: false,
    handler: callback
  };
}
Event.prototype.emit = function (eventName, args) {
  this.evnets[eventName].handler(args);
  if (this.evnets[eventName].once) { // 如果是once,则执行完成之后off掉
    this.off(eventName)
  }
}
Event.prototype.off = function (eventName) {
  delete this.evnets[eventName];
}
Event.prototype.once = function (eventName, callback) {
  this.evnets[eventName] = {
    once: true,
    handler: callback
  };
}

再优化?!

有时候,我们会把一个事件绑定多次的情况。

event.on('click', function (args) {
  console.log('第一次click')
  console.log(args);
});

event.on('click', function (args) {
  console.log('第二次click')
  console.log(args);
});

这种情况,我们希望两次绑定的事件都触发咯,但是上面的写法,第二次会覆盖第一次。这种情况处理也很简单,this.events[eventName]使用数组处理就好了,but!!!那样的话,我们的off方法就要修改,思路就是绑定的时候,要手动传入一个id。。。。

算了,这种实现简直就是反人类,如果有这种场景,那么用两个不同的eventName吧!

哪里有用到?

实际中,比如之前的jQuery有一个trigger方法、Vue的响应式设计、我们使用的promise等,底层还是借鉴了发布订阅模式的思想。

最后

第一次发文,求轻拍。。。