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

前言

对于前端同学而言,发布-订阅模式应该是最熟悉的设计模式了。平常写的最多的事件监听就是一个最好的例子。

var dom = document.querySelector('xxx');
dom.addEventListener('click', () => { //do something });
dom.click();

这里开发同学订阅这个dom对象的click事件,并且传入了一个回调函数。当这个事件被触发(用户点击),就会执行这个回调。当然,我们可以也可以订阅这个对象的其他事件,也可以多次订阅同一个事件并且传入不同的回调。

使用场景

这个设计模式的优点十分明显,他可以解耦发布者和订阅者,看一段业务中经常用到的场景。
假设一个页面需要一个接口来渲染三个模块。分别为A。B。C。当接口返回时,要调用对应模块的业务逻辑接口。

import { A, B, C } from 'dir';
getApi().then((data) => {
	A.renderA();
	B.renderB();
	C.renderC();
});

这里有几个问题

  1. 假如这个getApi是你负责的模块,而A B C模块都是分别由其他人维护的,你需要侵入到模块内部,来调用他们的方法。
  2. 如果业务逻辑发生变化,增加一个D模块,那么此时你需要在回调里面再新增D模块,再新增的话你还得再加。其实这是不合理的,不能因为有其他模块的介入我们就得修改一次代码,这样的强耦合会造成业务逻辑的不可维护。

这个时候就可以利用一下发布-订阅模式来解决这个问题。

我们修改一下上述代码

// event.js
class Event {
    constructor(){
        this.watchList = {};
    }

    listen(key,fn){
        if (this.watchList[key]) {
            this.watchList[key].push(fn);
        } else {
            this.watchList[key] = [fn];
        }
        
    }

    trigger(...args){
        const key = args.shift();
        if (!key) {
            return;
        }
        const fns = this.watchList[key];
        if (!fns) {
            return;
        }
        
        for(let i=0;i<fns.length;i++) {
            fns[i] && fns[i].apply(this,args);
        }
    }
}
export default new Event();

// A.js
import event from event

const A = {
	renderA:() => { // do something }
};

event.listen('data-ready',() => {
	A.renderA();
})


// B.js 和 C.js 同理


// page.js
import event from 'event';
getApi().then((data) => {
	event.trigger('data-ready',data);
});

这么一来,不管是A B C 模块的内部方法发生了改变,还是要新增其他的模块,请求API后的回调逻辑就不用再改动了。其他模块的人只要维护好他们自己的方法就行。

写在最后

除了解耦模块和模块之间的关系以外,这个设计模式在其他领域也常被用到,比如消息中间件的异步通信中,上游不用关心下游实时返回的结果,而是等结果产生了再调用对应的事件回调。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值