发布订阅模式你get了吗

268 阅读3分钟

前言

用一个简单的例子来分享下关于发布订阅模式的原理吧~

言覃想要买房,他拿着麻袋装好钱准备去售楼部买房,走进售楼部,接待人员很热情的接待他,言覃说出了他的需求后,接待人员就和他说:“不好意思哈,这位先生,你想要的房型已经卖完了,要不你留个微信,有房源这边就联系你”。

接下来,分析一下,首先只要有房源了言覃就能立刻拿下房子,也就是言覃已经留联系方式了(订阅)了,就等负责人发布房源(发布),接下来通过代码来实现吧~

快来和我一起去看看言覃拿下他的大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

image.png

如果言覃留下联系方式的时候(订阅),留下了一些要求(传参数),要求在买房的时候送些小礼物(输出传入的参数),怎么实现呢?

  • 修改下emit函数,在调用emit的时候,把参数传入进去
emit(type, gift) {
        this.events[type].forEach((fn) => fn(gift));
    }
  • 修改成功买房函数buy1
function buy1 (gift) {
    console.log('言覃买房成功!!!', gift);
}

言覃想要送个大冰箱

e.emit('houseSource', '大冰箱');

image.png

怎么实现椰汁买车位呢?

和上面言覃买房一样的实现方法

  • 定义一个成功买车位的函数buyCarPlace
function buyCarPlace() {
    console.log('椰汁买车位成功!!!');
}
  • 订阅车位
e.on('carPlaceSource', buyCarPlace);
  • 发布车位
e.emit('carPlaceSource');

成功拿下车位咯!

image.png

如果我要实现只能订阅一次,怎么实现呢?也就是言覃留下很多个联系方式去订阅,只订阅一个

  • 定义一个取消函数方法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',  '大冰箱');

实现了只能订阅一次

image.png

换一种说法,怎么实现发布多次只执行一次?也就是负责人发布了很多房源,言覃只能选一个房子

  • 修改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');

image.png

结语

通过买房的例子大家有理解吗?希望可以给大家带来一些帮助哦

image.png