You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

受限场景下TypeScript对象实现独立类型化事件发射器的最优方案

实现带类型负载的实例级事件发射器方案

一、自行实现轻量泛型事件类

自己写一个极简的泛型事件类是最灵活的选择,完全满足你的所有限制,而且代码量极小:

// 泛型事件发射器,支持指定负载类型
class TypedEvent<T> {
  private callbacks: Array<(payload: T) => void> = [];

  // 添加回调,返回移除函数方便取消监听
  addCallback(callback: (payload: T) => void) {
    this.callbacks.push(callback);
    return () => {
      this.callbacks = this.callbacks.filter(cb => cb !== callback);
    };
  }

  // 触发事件,传递负载
  emit(payload: T) {
    // 复制回调数组,避免触发时移除回调导致遍历异常
    [...this.callbacks].forEach(callback => callback(payload));
  }

  // 可选:清空所有回调
  removeAllCallbacks() {
    this.callbacks = [];
  }
}

// 你的基础类
class BaseClass {
  public someProperty: number = 0;
}

// 业务类,把TypedEvent作为成员变量使用(组合而非继承)
class ProcessDoer extends BaseClass {
  public onProcessDone: TypedEvent<number>;

  constructor() {
    super();
    this.onProcessDone = new TypedEvent<number>();

    setInterval(() => {
      this.someProperty = Math.random();
      this.onProcessDone.emit(this.someProperty);
    }, 1000);
  }
}

// 使用示例
const processDoer1 = new ProcessDoer();
const processDoer2 = new ProcessDoer();

// 只监听processDoer2的事件
const unsubscribe = processDoer2.onProcessDone.addCallback((result) => {
  console.log("第二个ProcessDoer完成任务,结果:", result);
});

// 要取消监听的话直接调用unsubscribe()
// unsubscribe();

这个实现完美匹配你的需求:

  • 无需继承:通过组合方式把事件类作为成员变量,完全不影响原有类的继承关系
  • 封装性:只有持有ProcessDoer实例引用的代码才能访问onProcessDone,没有全局注册入口
  • 实例级监听:每个ProcessDoer实例的onProcessDone都是独立的,监听只会针对特定实例生效

二、现成npm包方案

如果不想自己造轮子,这些轻量的事件库可以直接用,同样通过组合方式集成:

1. tiny-emitter(超轻量)

tiny-emitter体积极小,API简洁,配合类型声明支持TypeScript:

安装命令:

npm install tiny-emitter
npm install -D @types/tiny-emitter

使用示例:

import Emitter from 'tiny-emitter';

class ProcessDoer extends BaseClass {
  // 泛型指定事件与负载类型的映射
  public onProcessDone: Emitter<{
    'done': [number] // 事件名对应回调参数的类型数组
  }>;

  constructor() {
    super();
    this.onProcessDone = new Emitter();

    setInterval(() => {
      this.someProperty = Math.random();
      this.onProcessDone.emit('done', this.someProperty);
    }, 1000);
  }
}

// 监听特定实例的事件
processDoer2.onProcessDone.on('done', (result) => {
  console.log("第二个ProcessDoer完成任务,结果:", result);
});

2. mitt(天生支持TS泛型)

mitt是另一个极简库,原生支持TypeScript泛型,类型定义更直观:

安装命令:

npm install mitt

使用示例:

import mitt from 'mitt';

// 定义事件类型映射
type ProcessEvents = {
  processDone: number;
};

class ProcessDoer extends BaseClass {
  public onProcessDone: mitt.Emitter<ProcessEvents>;

  constructor() {
    super();
    this.onProcessDone = mitt<ProcessEvents>();

    setInterval(() => {
      this.someProperty = Math.random();
      this.onProcessDone.emit('processDone', this.someProperty);
    }, 1000);
  }
}

// 监听特定实例的事件
processDoer2.onProcessDone.on('processDone', (result) => {
  console.log("第二个ProcessDoer完成任务,结果:", result);
});

这些包的优势:

  • 无需继承,都是实例化后作为成员变量使用
  • 完全是实例级事件,没有全局污染
  • 自带TypeScript类型支持,满足带类型负载的需求

内容的提问来源于stack exchange,提问作者goose_lake

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 18:33:25