JavaScript—发布-订阅模式

现实举例:在某应用上预约了一个抢票活动,那么在抢票开始前的一段时间内,平台会自动将抢票活动通知重复发送给你,以提醒你不要忘记抢票。

在这里提到的某应用就是发布者,而报名活动的用户则是订阅者。

1.概念

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。

2.实现发布订阅模式

首先要知道发布订阅模式的三大组成:

  1. 发布对象:事件发布者,将事件传给调度中心

  1. 调度中心:发布、订阅对象之间的中介,将订阅者与发布者联系起来

  1. 订阅对象:订阅事件,向调度中心发起订阅

step1

定义全局发布—订阅对象

作用:实现代码复用,减少订阅对象与发布对象的耦合度

const Event = (function () {

})();

step2

为全局对象添加相关方法和属性等

const Event = (function () {
    //调度中心
    const clientList = {};
    //on方法,添加订阅
    const on = function () {

    };
    //emit方法,发布事件
    const emit = function () {

    }
    //off方法,取消订阅
    const off = function () {

    }
})();

on方法

接收两个参数,一个是键名(用来给事件增加唯一标识,订阅者只需传递唯一标识,然后发布者就可以根据唯一标识发布用户想要访问的事件了)一个是回调函数(订阅者想要访问的事件,比如抢票活动通知事件)

const on = function (key, callback) {
    //没有唯一标识,就创建一个
    if (!clientList[key]) {
        clientList[key] = [];
    }
    //将回调传进数组中
    clientList[key].push(callback);
};

emit方法

获取唯一标识所对应的事件,并执行获取到的事件

const emit = function () {
    const key = Array.prototype.shift.call(arguments);
    callbacks = clientList[key];
    if (!callbacks || callbacks.length === 0) {
        return false;
    }
    callbacks.forEach(callback => {
        callback.apply(this, arguments);
    });
}

off方法

如果没有传callback参数,则把key对应的值清空。否则,只删除callback

const off = function (key, callback) {
    const callbacks = clientList[key];
    if (!callbacks) {
        return false;
    }
    if (!callback) {
        callbacks && (callbacks.length = 0);
    } else {
        for (let i = 0; i < callbacks.length; i++) {
            if (callbacks[i] === callback) {
                callbacks.splice(i, 1);
            }
        }
    }
};

完整版

const Event = (function () {
    //调度中心
    const clientList = {};
    //on方法,添加订阅
    const on = function (key, callback) {
        if (!clientList[key]) {
            clientList[key] = [];
        }
        clientList[key].push(callback);
    };
    //emit方法,发布事件
    const emit = function () {
        const key = Array.prototype.shift.call(arguments);
        callbacks = clientList[key];
        if (!callbacks || callbacks.length === 0) {
            return false;
        }
        callbacks.forEach(callback => {
            callback.apply(this, arguments);
        });
    };
    //off方法,取消订阅
    const off = function (key, callback) {
        const callbacks = clientList[key];
        if (!callbacks) {
            return false;
        }
        if (!callback) {
            callbacks && (callbacks.length = 0);
        } else {
            for (let i = 0; i < callbacks.length; i++) {
                if (callbacks[i] === callback) {
                    callbacks.splice(i, 1);
                }
            }
        }
    };
    return {
        on,
        emit,
        off
    }
})();

step3

使用,拿抢票活动举例,有两位用户订阅了抢票通知,如行1 行4,当临近抢票阶段(假设临近了),系统会自动发布对应事件给当事人,如行7 行8。但是用户2023在20小时后又有其它安排了,不得不取消这次预约,如行9。

Event.on('用户2022', fn1 = function (information) {
    console.log(information);
})
Event.on('用户2023', fn2 = function (information) {
    console.log(information);
})
Event.emit('用户2022', '您预约的公益讲座抢票活动将在10分钟后开启');
Event.emit('用户2023', '您预约的小型演唱会(主楼)抢票活动将在20小时后开启');
Event.off('用户2023', fn2);

结尾:

发布-订阅模式优点:

对象间的解耦,发布者与订阅者完全不需要事先知道对方的存在,只需要Event将它们连接起来即可

发布-订阅缺点:

创建订阅者要占用一定的内存,也可能出现,虽然订阅了,但是事件最后都没有发生的情况。

过度使用的话,对象间(发布者与订阅者)的联系也不好梳理,后续会出现难以维护、理解的情况。

问题:

观察者模式与发布-订阅模式的区别:

发布订阅模式其实属于广义上的观察者模式。

在观察者模式中,观察者需要直接订阅目标事件。在目标发出内容改变的事件后,直接接收事件并作出响应。

而在发布订阅模式中,发布者和订阅者之间多了一个调度中心。调度中心一方面从发布者接收事件,另一方面向订阅者发布事件,订阅者需要在调度中心中订阅事件。通过调度中心实现了发布者和订阅者关系的解耦。使用发布订阅者模式更利于我们代码的可维护性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值