关于订阅发布模式

Apr 13, 2024·
Sam.C
Sam.C
· 2 min read

node 是一个事件循环驱动的js运行时。EventEmitter 是其核心模块,这个模块可以自定义事件,实现订阅发布模式。

事件订阅和发布模式的关键是解耦。它允许不同的组件或模块能够独立地进行通信,而不需要直接依赖彼此的具体实现细节。这种解耦可以提高代码的可维护性、灵活性和可扩展性。

下面通过一个例子来说明事件订阅和发布的实际用途:

假设你有一个应用程序,其中包含一个用户注册模块和一个发送欢迎邮件的模块。当用户在注册模块中成功注册时,你希望发送欢迎邮件。但是你不希望注册模块直接调用发送邮件的功能,而是希望它只负责触发一个事件,然后由发送邮件的模块来订阅并处理该事件

以下是一个用户注册时,给用户发送欢迎邮件的示例:

const EventEmitter = require('events');

class UserRegistration {
  constructor() {
    this.eventEmitter = new EventEmitter();
  }

  registerUser(username) {
    // 用户注册逻辑...

    // 触发事件
    this.eventEmitter.emit('userRegistered', username);
  }
}

class WelcomeEmailSender {
  constructor(userRegistration) {
    this.userRegistration = userRegistration;

    // 订阅事件
    this.userRegistration.eventEmitter.on('userRegistered', (username) => {
      this.sendWelcomeEmail(username);
    });
  }

  sendWelcomeEmail(username) {
    // 发送欢迎邮件逻辑...
    console.log(`Sending welcome email to ${username}`);
  }
}

// 创建实例
const userRegistration = new UserRegistration();
const welcomeEmailSender = new WelcomeEmailSender(userRegistration);

// 用户注册时触发事件
userRegistration.registerUser('John');

订阅发布模式本身也是一种常见的消息传递模式,可以用于实现类似于站内信的功能。在这种模式下,你可以定义一个中心的消息代理或消息队列,其他组件或模块可以订阅感兴趣的主题或事件,以接收相关的消息。但是订阅发布模式在后端内部使用时,主要用于模块之间的解耦和消息传递,而不直接与前端进行实时交互。要使前端能够实时获取站内信,还需要配合SSE或者WS技术实现。

以下是一个简单的示例,演示了如何使用订阅发布模式实现站内信功能:

class MessageBroker {
  constructor() {
    this.subscribers = {};
  }

  subscribe(topic, callback) {
    if (!this.subscribers[topic]) {
      this.subscribers[topic] = [];
    }
    this.subscribers[topic].push(callback);
  }

  publish(topic, message) {
    const subscribers = this.subscribers[topic];
    if (subscribers) {
      subscribers.forEach(callback => callback(message));
    }
  }
}

// 创建消息代理实例
const messageBroker = new MessageBroker();

// 订阅站内信主题
messageBroker.subscribe('inbox', message => {
  console.log('New message in inbox:', message);
});

// 发布新消息
messageBroker.publish('inbox', 'Hello! You have a new message.');

// 输出:
// New message in inbox: Hello! You have a new message.