前言
用一个简单的例子来分享下关于发布订阅模式的原理吧~
言覃想要买房,他拿着麻袋装好钱准备去售楼部买房,走进售楼部,接待人员很热情的接待他,言覃说出了他的需求后,接待人员就和他说:“不好意思哈,这位先生,你想要的房型已经卖完了,要不你留个微信,有房源这边就联系你”。
接下来,分析一下,首先只要有房源了言覃就能立刻拿下房子,也就是言覃已经留联系方式了(订阅)了,就等负责人发布房源(发布),接下来通过代码来实现吧~
快来和我一起去看看言覃拿下他的大house~~~
正文
首先,定义一个类Event,在该类定义实现发布和订阅的函数方法
class Event {
constructor() {
this.events = {};
}
// 订阅
on(type, fn) {
if(!this.events[type]) {
this.events[type] = [];
}
this.events[type].push(fn);
}
// 发布
emit(type) {
this.events[type].forEach((fn) => fn());
}
}
定义一个实例对象
const e = new Event();
定义言覃买下房子的函数
function buy1 (gift) {
console.log('言覃买房成功!!!', gift);
}
言覃留下联系方式(订阅)
e.on('houseSource', buy1);
负责人发布房源
e.emit('houseSource');
接下来,恭喜言覃拿下他的大house
如果言覃留下联系方式的时候(订阅),留下了一些要求(传参数),要求在买房的时候送些小礼物(输出传入的参数),怎么实现呢?
- 修改下emit函数,在调用emit的时候,把参数传入进去
emit(type, gift) {
this.events[type].forEach((fn) => fn(gift));
}
- 修改成功买房函数buy1
function buy1 (gift) {
console.log('言覃买房成功!!!', gift);
}
言覃想要送个大冰箱
e.emit('houseSource', '大冰箱');
怎么实现椰汁买车位呢?
和上面言覃买房一样的实现方法
- 定义一个成功买车位的函数buyCarPlace
function buyCarPlace() {
console.log('椰汁买车位成功!!!');
}
- 订阅车位
e.on('carPlaceSource', buyCarPlace);
- 发布车位
e.emit('carPlaceSource');
成功拿下车位咯!
如果我要实现只能订阅一次,怎么实现呢?也就是言覃留下很多个联系方式去订阅,只订阅一个
- 定义一个取消函数方法off
off(type, fn) {
this.events[type] = this.events[type].filter((item) => item !== fn);
}
- 在constructor定义一个数组onceFn来判断是否已经订阅
constructor() {
this.events = {};
this.onceFn = [];
}
- 定义一个once实现只能订阅一次
once(type, fn) {
if(this.onceFn.includes(fn)) { // 只能订阅一次
return;
}
this.onceFn.push(fn);
this.on(type, fn);
}
- 定义椰汁买房函数
function buy2 (gift) {
console.log('椰汁买房成功!!!', gift);
}
测试:
e.once('houseSource',buy1);
e.once('houseSource',buy2);
e.once('houseSource',buy1);
e.once('houseSource',buy1);
e.emit('houseSource', '大冰箱');
实现了只能订阅一次
换一种说法,怎么实现发布多次只执行一次?也就是负责人发布了很多房源,言覃只能选一个房子
- 修改once函数
once(type, fn) {
const reWriteFn = () => { // 发布多次只执行一次
fn();
this.off(type, reWriteFn);
};
this.on(type, reWriteFn);
}
测试:
e.once('houseSource',buy1);
e.emit('houseSource');
e.emit('houseSource');
e.emit('houseSource');
e.emit('houseSource');
结语
通过买房的例子大家有理解吗?希望可以给大家带来一些帮助哦