🧠 一、Emitter 是什么?
Emitter 是 HarmonyOS 提供的一个轻量级事件通信机制 ,用于实现进程内、线程间的异步事件通知与订阅 。它类似于 Node.js 中的 EventEmitter,但为 ArkTS 框架和线程模型进行了专门优化,尤其适合组件解耦、Worker 通信、UI 与后台同步等场景。
⚙️ 二、Emitter 的核心设计原理
1. 事件队列机制
- Emitter内部维护了一个 事件队列 ,所有通过- emit发布的事件都会进入该队列。
- 队列以 FIFO(先进先出) 的方式异步串行执行事件回调。
- 通过设置事件优先级(如 LOW / IMMEDIATE)影响事件在队列中的调度顺序。
2. 异步串行调度
- 所有订阅的回调函数在事件被触发后会逐个执行。
- 如果某个回调耗时过长,可能会阻塞后续事件执行,所以建议回调中避免同步阻塞逻辑。
3. 线程安全设计
- Emitter 本质上是一种线程间消息传递机制,但其使用方式简洁,无需复杂的线程同步操作。
- 适用于主线程(UI线程)与 Worker线程(如后台处理)之间的数据通信。
🛠️ 三、Emitter 的核心接口详解
| 方法名 | 描述 | 使用示例 | 
|---|---|---|
| on(event, callback) | 注册事件监听,持续有效,需手动取消 | emitter.on({ eventId: 1 }, cb) | 
| once(event, callback) | 注册事件监听,只触发一次后自动移除 | emitter.once({ eventId: 1 }, cb) | 
| off(eventId, callback) | 注销指定事件和回调函数的订阅 | emitter.off(1, cb) | 
| emit(event, data) | 发布事件并传递数据 | emitter.emit({ eventId: 1 }, { data: xxx }) | 
✅ 接口参数详解:
event: { eventId: string | number, priority?: EventPriority }
- eventId: 自定义事件标识(可使用字符串或数字)
- priority: 事件优先级(可选)
data: { data: any }
- 用户传递的事件数据对象
🧵 四、线程与进程模型下的使用
场景:主线程与 Worker线程 通信
1. Worker 线程发布事件
            
            
              ts
              
              
            
          
          // worker线程
emitter.emit({ eventId: 'background_done' }, { data: '处理完成' });2. 主线程监听事件
            
            
              ts
              
              
            
          
          emitter.on({ eventId: 'background_done' }, (eventData) => {
  this.result = eventData.data;
  this.updateUI(); // 注意线程安全性
});💡 线程间通信不需要共享变量或 postMessage,Emitter 自动桥接数据流
📦 五、状态管理与 UI 刷新注意事项
常见问题:UI 未响应事件更新?
原因:
- 回调中更新的数据变量 未被响应式装饰器(如 @ObservedV2、@State、@Provide)修饰。
- 回调中使用了早绑定的箭头函数,未捕获响应式代理对象。
正确做法:
            
            
              ts
              
              
            
          
          @ObservedV2
class ViewModel {
  @Trace count: number = 0;
  increment() {
    this.count++;
  }
}
// 生命周期绑定回调
aboutToAppear() {
  emitter.on({ eventId: 'count_update' }, () => {
    this.viewModel.increment();
  });
}🧪 六、常见使用场景
| 场景 | 描述 | 
|---|---|
| ✅ 跨线程通信 | 主线程与 Worker 通信,替代 postMessage 等复杂机制 | 
| ✅ 模块解耦 | 非父子组件间的数据广播,如登录成功后全局通知 | 
| ✅ 动态事件订阅 | 某个业务模块需要在运行时动态监听任务完成状态 | 
| ✅ UI控制逻辑 | 后台服务状态变化驱动界面展示或提示 | 
📊 七、与 EventHub 的差异总结
| 特性 | Emitter | EventHub | 
|---|---|---|
| 使用场景 | 跨线程通信,模块解耦 | 组件内通信,UI层事件传递 | 
| 线程支持 | 支持主线程 + Worker线程 | 仅支持 UI线程 | 
| 事件调度 | 异步、优先级队列 | 同步、立即执行 | 
| 生命周期 | 手动取消订阅 | 生命周期自动释放(Stage组件) | 
| 响应式集成 | 需要配合状态装饰器 | 更紧密集成 UI 生命周期 | 
🧹 八、资源管理与内存泄漏风险
✔️ 正确做法
- 页面或模块销毁时务必手动调用 off方法取消订阅
- 推荐使用 once替代短期监听,避免忘记取消
示例:
            
            
              ts
              
              
            
          
          private onCallback = (data) => { ... };
aboutToAppear() {
  emitter.on({ eventId: 'task' }, this.onCallback);
}
aboutToDisappear() {
  emitter.off('task', this.onCallback);
}🔒 九、最佳实践建议
| 建议 | 描述 | 
|---|---|
| ✅ 封装事件工具类 | 统一事件管理,封装 on/off/emit逻辑,避免重复代码 | 
| ✅ 使用枚举管理事件ID | 防止硬编码,提升可读性 | 
| ✅ 避免多个回调监听同一个事件 | 可能造成重复响应,应通过中间层转发 | 
| ✅ 日志跟踪事件流程 | emit / on 处记录日志便于调试 | 
📁 十、封装工具类示例(建议应用)
            
            
              ts
              
              
            
          
          export enum AppEvent {
  LOGIN_SUCCESS = 'login_success',
  DATA_READY = 'data_ready',
}
export class EmitterUtil {
  private static registry = new Map<string, Function[]>();
  static on(eventId: string, cb: Function) {
    emitter.on({ eventId }, cb);
    const list = this.registry.get(eventId) || [];
    list.push(cb);
    this.registry.set(eventId, list);
  }
  static emit(eventId: string, data: any) {
    emitter.emit({ eventId }, { data });
  }
  static off(eventId: string) {
    const list = this.registry.get(eventId) || [];
    list.forEach(cb => emitter.off(eventId, cb));
    this.registry.delete(eventId);
  }
}✅ 总结一句话
Emitter 是 HarmonyOS 架构中适用于线程间、模块间通信的高效、非侵入式事件调度器。通过合理封装与状态集成,可实现高内聚、低耦合的通信机制。