ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Javacript实现简单的发布订阅模式或观察者模式的进阶版

2021-10-21 17:34:20  阅读:211  来源: 互联网

标签:const 进阶 list 模式 listener Javacript key orange 监听


/**
* 实现一个简单的观察者模式
*/

const shop = {
apple: 5, // 苹果5元
potato: 2, // 马铃薯 2元
tomato: 3, // 西红柿 3元
orange: 7,
}

/**
* 现在我们有一个便利店的实例对象,目标是需要增加对商品价格的监听,当商品价格发生变化时,触发对应的事件。
* 1、小明关注苹果价格变化
* 2、小刚关注橙子价格变化
* 3、当价格变化时,自动触发对应的事件
*/

class Pubsub {
constructor() {
}

list = {};

// 监听方法,添加监听者,监听对象,和监听事件的方法
listen = (key, listener, fn) => {
const { list = {} } = this;
if (!list[key]) {
list[key] = [];
}
list[key].push({ listener, fn });
return () => this.remove(key, listener, fn);
}

// 发布消息的方法
publish = (key, price) => {
const { list = {} } = this;
if (list[key]) {
list[key].forEach((item) => {
const { listener, fn } = item;
fn.call(null, listener, price);
})
}
}

// 移除监听的方法
remove = (key, listener, fn) => {
const { list = {} } = this;
if (!listener) { // 如果没有传入监听人,则移除对该属性的所有监听
delete list[key];
return;
}

if (!fn || typeof fn !== 'function') { // 如果没有传入fn,则移除此监听者的所有监听事件
list[key] = list[key].filter(x => x.listener !== listener);
return;
}

const index = list[key].findIndex(x => x.listener === listener && x.fn === fn);
list[key].splice(index, 1);
if (list[key].length === 0) { // 如果移除监听后,监听列表的长度变为0, 则移除这个监听
delete list[key];
}
}
}

const pubsub = new Pubsub();

const event1 = pubsub.listen('apple', '小明', (listener, price) => {
console.log(`${listener}关注的apple的最新价格是${price}`);
})

const enent2 = pubsub.listen('orange', '小明', (listener, price) => {
console.log(`${listener}关注的orange的最新价格是${price}`);
})

const enent3 = pubsub.listen('orange', '小刚', (listener, price) => {
console.log(`${listener}关注的orange的最新价格是${price}`);
})

const set = (target, key, value, receiver) => {
if (receiver[key] !== value) {
pubsub.publish(key, value);
}
return Reflect.set(target, key, value, receiver);
}

const observable = (obj) => new Proxy(obj, { set });

const newShop = observable(shop);

newShop.apple = 5;

newShop.apple = 6;
/** 小明关注了苹果的价格,苹果价格变更将会触发事件
** console.log将会输出: 小明关注的apple的最新价格是6元
**/

newShop.tomato = 10;
/** 无人关注西红柿价格,不会触发事件 **/

newShop.orange = 11;
/** 小明关注了橙子的价格,橙子价格变更将会触发事件
** console.log将会输出: 小明关注的orange的最新价格是11元
**/

/** 小刚关注了橙子的价格,橙子价格变更将会触发事件
** console.log将会输出: 小刚关注的orange的最新价格是11元
**/

// 移除小明对app事件的监听
event1();

newShop.apple = 7;
/** 苹果监听已经被移除,无人关注苹果价格,不会触发事件 **/

newShop.orange = 12;
/** 小明关注了橙子的价格,橙子价格变更将会触发事件
** console.log将会输出: 小明关注的orange的最新价格是12元
**/

/** 小刚关注了橙子的价格,橙子价格变更将会触发事件
** console.log将会输出: 小刚关注的orange的最新价格是12元
**/


标签:const,进阶,list,模式,listener,Javacript,key,orange,监听
来源: https://www.cnblogs.com/liquanjiang/p/15434339.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有