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

2021/10/21 17:39:31

本文主要是介绍Javacript实现简单的发布订阅模式或观察者模式的进阶版,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

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

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元
 **/




这篇关于Javacript实现简单的发布订阅模式或观察者模式的进阶版的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程