设计模式之发布订阅模式

什么是发布订阅模式?

发布订阅模式EventEmitter是一种设计模式,它是一种编程思想,它可以帮助我们解决”回调地狱“的问题。Promise 也是借鉴了发布订阅设计模式的思想来实现的。

发布订阅模式核心依赖于 Publisher(发布者)、Subscriber(订阅者)、Event Channel(消息中心)

Publisher(发布者)

向消息中心发布消息

Subscriber(订阅者)

订阅消息中心中的消息

Event Channel(消息中心)

负责存储信息和订阅者的对应关系,有消息触发时,负责通知订阅者。

实现发布订阅模式

class PubSub {
  constructor() {
    // 定义一个消息中心,用于存储消息与订阅者的消息。
    this.events = {};
  }

  // 订阅者
  subscribe(event, callback) {
    // 如果已经有订阅者订阅,直接添加
    if (this.events[event]) {
      this.events[event].push(callback);
    } else {
      // 没有订阅者,以数组的形式放进去
      this.events[event] = [callback];
    }
  }

  // 发布者
  publish(event, ...agrs) {
    const subscribedEnvets = this.events[event];
    // 如果存在订阅者,则一次将消息通知给订阅者
    if (subscribedEnvets && subscribedEnvets.length) {
      subscribedEnvets.forEach((callback) => {
        callback.call(this, ...agrs);
      });
    }
  }

  // 取消订阅
  unsubscribe(event, callback) {
    const subscribedEnvets = this.events[event];
    // 如果存在订阅者,则将指定的订阅者移除
    if (subscribedEnvets && subscribedEnvets.length) {
      this.events[event] = this.events[event].filter((cb) => cb !== callback);
    }
  }
}
const pubSub = new PubSub();

// 接受订阅消息的回调函数
const subscribeCallback = (message) => {
  console.log("message", message);
};

pubSub.subscribe("request", subscribeCallback);
pubSub.publish("request", "收到消息");

// 取消订阅后不会接受消息
pubSub.unsubscribe("request", subscribeCallback);
pubSub.publish("request", "收到消息2");

// log
// message 收到消息

解决回调地狱

以下代码掩饰了网络请求,第二个网络请求依赖于第一个网络请求,第三个网络请求依赖于第二个网络请求,这就是典型的回调地狱。

request("https://www.baidu.com", (error, response) => {
  if (!error && response.statusCode === 200) {
    console.log("request1");
    request("https://www.baidu.com", (error, response) => {
      if (!error && response.statusCode === 200) {
        console.log("request2");
        request("https://www.baidu.com", (error, response) => {
          if (!error && response.statusCode === 200) {
            console.log("request3");
          }
        });
      }
    });
  }
});

通过发布订阅模式解决回调地狱的问题,当第一个网络请求成后request1Success发布消息,订阅者request1Success收到消息后执行请求第二个网络请求,以此类推解决回调地狱的问题。

const pubSub = new PubSub();
request("https://www.baidu.com", function (error, response) {
  if (!error && response.statusCode == 200) {
    console.log("request1");
    // 发布请求1成功消息
    pubSub.publish("request1Success");
  }
});

pubSub.subscribe("request1Success", () => {
  request("https://www.baidu.com", function (error, response) {
    if (!error && response.statusCode == 200) {
      console.log("request2");
      // 发布请求2成功消息
      pubSub.publish("request2Success");
    }
  });
});

pubSub.subscribe("request2Success", () => {
  request("https://www.baidu.com", function (error, response) {
    if (!error && response.statusCode == 200) {
      console.log("request3");
      // 发布请求3成功消息
      pubSub.publish("request3Success");
    }
  });
});

总结

通过发布订阅模式可以解决回调地狱的问题。

发布订阅模式对模块进行了解耦,我们无需关心是否存在订阅者,只需要关心发布出来的事件。

最后

感谢你的阅读~

如果你有任何的疑问欢迎您在后台私信,我们一同探讨学习!

如果觉得这篇文章对你有所帮助,点赞、在看是最大的支持!

你可能感兴趣的:(JavaScript,设计模式)