简写一个订阅发布

46 阅读1分钟

简写一个订阅发布

type Callbacks = (() => void)[]
export class EventEmiter {
  events: Map<string, Callbacks> = new Map()
  constructor() {
    this.events = new Map()
  }
  subscript(event: string, callback: () => void) {
    if (!this.events.has(event)) {
      this.events.set(event, [])
    }
    this.events.get(event)!.push(callback)
    return this; // 支持链式调用
  }
  public(event: string, ...args: []) {
    console.log(`发布了事件: '${event}'`);
    // 检查该事件是否有订阅者
    if (this.events.has(event)) {
      // 获取该事件的所有回调函数
      const callbacks = this.events.get(event)!.slice(); // 创建副本,防止在遍历时修改原数组
      // 执行每个回调函数
      callbacks.forEach(callback => {
        try {
          callback.apply(this, args); // 使用 apply 传递参数
        } catch (error) {
          console.error(`执行 '${event}' 事件的回调函数时出错:`, error);
        }
      });
    } else {
      console.log(`事件 '${event}' 没有订阅者。`);
    }
    return this; // 支持链式调用
  }
  once(event: string, callback: () => void) {
    // 创建一个包装函数
    const onceWrapper = (...args: []) => {
      // 在执行原始回调之前,先取消订阅这个包装函数
      this.unsubscript(event, onceWrapper);
      // 执行原始回调函数
      callback.apply(this, args);
    };
    // 将包装函数作为真正的订阅者
    this.subscript(event, onceWrapper);
    console.log(`订阅了事件 (仅一次): '${event}'`);
    return this; // 支持链式调用
  }
  getLength(event?: string) {
    if (event) {
      return !this.events.has(event) ? 0 : this.events.get(event)!.length
    }
    return this.events.size
  }
  unsubscript(event: string, callback: () => void) {
    if (!this.events.has(event)) {
      console.log(`事件 '${event}' 不存在或没有订阅者。`);
      return this;
    }
    if (!callback) {
      // 如果没有指定具体回调函数,则移除该事件的所有订阅者
      this.events.delete(event);
      console.log(`已取消所有 '${event}' 事件的订阅。`);
    } else {
      // 如果指定了回调函数,则只移除该回调
      const callbacks = this.events.get(event)!
      const index = callbacks.indexOf(callback);
      if (index > -1) {
        callbacks.splice(index, 1);
        console.log(`取消订阅了事件: '${event}'`);
        // 如果移除后数组为空,可以清理 Map
        if (callbacks.length === 0) {
          this.events.delete(event);
        }
      } else {
        console.log(`在事件 '${event}' 中未找到指定的回调函数。`);
      }
    }
    return this; // 支持链式调用
  }
  clear() {
    this.events.clear()
  }
}

// 使用
const ev = new EventEmiter()
const fn1 = () => console.log('fn1')
const fn2 = () => console.log('fn2')
const fn3 = () => console.log('fn3');
ev.subscript('1', fn1)
ev.once('1', fn2)
ev.subscript('1', fn3)

<button onClick={() => { ev.public('1') }}> public </button>