js 发布订阅模式

83 阅读1分钟

在 JavaScript 中,可以通过以下方式实现 发布订阅模式:

class EventEmitter {
  constructor() {
    this.events = {};
  }

  // 订阅事件
  on(eventName, callback) {
    if (!this.events[eventName]) {
      this.events[eventName] = [];
    }
    this.events[eventName].push(callback);
  }

  // 发布事件
  emit(eventName, data) {
    const callbacks = this.events[eventName];
    if (callbacks) {
      callbacks.forEach(callback => callback(data));
    }
  }

  // 取消订阅
  off(eventName, callback) {
    const callbacks = this.events[eventName];
    if (callbacks) {
      this.events[eventName] = callbacks.filter(cb => cb !== callback);
    }
  }

  // 一次性订阅
  once(eventName, callback) {
    const wrappedCallback = (...args) => {
      callback(...args);
      this.off(eventName, wrappedCallback);
    };
    this.on(eventName, wrappedCallback);
  }
}

使用示例

const eventEmitter = new EventEmitter();

// 订阅事件
eventEmitter.on('greet', (name) => {
  console.log(`Hello, ${name}!`);
});

// 发布事件
eventEmitter.emit('greet', 'Alice');

// 一次性订阅
eventEmitter.once('greetOnce', (name) => {
  console.log(`This is a one-time greeting: Hello, ${name}!`);
});

eventEmitter.emit('greetOnce', 'Bob'); // 输出一次
eventEmitter.emit('greetOnce', 'Charlie'); // 不会输出

// 取消订阅
const greetCallback = (name) => {
  console.log(`Goodbye, ${name}!`);
};

eventEmitter.on('goodbye', greetCallback);
eventEmitter.emit('goodbye', 'David');

eventEmitter.off('goodbye', greetCallback);
eventEmitter.emit('goodbye', 'Eve'); // 不会输出
  • on(eventName, callback) : 订阅一个事件,将回调函数添加到事件的监听列表中。
  • emit(eventName, data) : 发布一个事件,调用所有订阅该事件的回调函数,并传递数据。
  • off(eventName, callback) : 取消订阅一个事件,从事件的监听列表中移除指定的回调函数。
  • once(eventName, callback) : 一次性订阅一个事件,回调函数在第一次触发后自动取消订阅。

通过这种方式,可以实现组件之间的松耦合通信,提高代码的可维护性和扩展性。