HIGH 还是 LOW?HarmonyOS 事件优先级的实际作用详解
文章目录前言泛型参数让事件数据有类型on 的原始 GenericEventData 结构事件优先级HIGH vs LOW不传优先级时的默认行为实际项目中的类型设计建议写在最后前言近期发现一款很有意思的HarmonyOS 三方库, 地址 pura/harmony-utils(V1.4.0) , 作者是桃花镇童长老, 我这里也是直接通过该作者公布的源码进行案例编写进行,写了到目前写了一部分demo ,感觉确实很有帮助,这里呢也是开始写一个系列的演示demo 供大家参考。如有帮助可以在OpenHarmony中进行下载安装进行使用哦案例demo导航展示↓↓↓↓↓↓接下来言归正传 ↓↓↓↓用了一段时间 EmitterUtil你可能会注意到它的 API 都带着string这样的泛型参数还有发消息时可以指定HIGH、LOW优先级。这两个特性对初学者来说可能有点陌生这篇文章专门来解释它们是干什么用的、该怎么用。泛型参数让事件数据有类型先说泛型。在EmitterUtilDemoPage里你会看到所有的订阅和发布都带了string或其他类型参数// 订阅时指定泛型EmitterUtil.onSubscribestring(EVT_NORMAL,(msg){this.addLog([onSubscribe] 第${this.onSubCount}次 →${msg});});// 发布时也指定泛型EmitterUtil.poststring(EVT_NORMAL,你好 Emitter,emitter.EventPriority.HIGH);为什么要加string这是 TypeScript/ArkTS 的泛型机制。如果你不加类型参数回调收到的msg就是any类型访问任何属性都没有类型提示容易出错。加了string之后编译器知道这个事件的数据是字符串回调参数msg自动推导为string类型在 IDE 里能看到属性提示写错了编译期就报错如果要传对象怎么办先定义 interface 或 classinterfaceMsgItem{time:string;text:string;}然后在订阅和发布时使用MsgItemEmitterUtil.onSubscribeMsgItem(EVT_TYPED,(msg){// msg.time 和 msg.text 都有类型提示this.addLog(时间:${msg.time}, 内容:${msg.text});});EmitterUtil.postMsgItem(EVT_TYPED,{time:10:00,text:测试消息});这就是泛型的价值用同一套 API 传任意类型的数据同时保持类型安全。on 的原始 GenericEventData 结构on方法接收的是原始的GenericEventData对象需要通过.data属性取值privatenamedCallback:Callbackemitter.GenericEventDatastring(data){// data 是 GenericEventDatastring// data.data 才是你发送的字符串this.addLog([on精准] 收到:${data.data});};// 注册EmitterUtil.onstring(EVT_TYPED,this.namedCallback);GenericEventDataT的结构大致是// GenericEventData 结构简化interfaceGenericEventDataT{data?:T;// 你发送的数据}所以取数据要用data.data不要漏掉这一层。onSubscribe在这里帮你做了解包所以直接回调的就是T类型的值。这是它和on最大的使用体验差异。事件优先级HIGH vs LOWHarmonyOS 的 emitter 支持消息优先级有三个级别EventPriority.IMMEDIATE立即处理最高EventPriority.HIGH高优先级EventPriority.LOW低优先级默认演示页里展示了 HIGH 和 LOW 两种// HIGH 优先级EmitterUtil.poststring(EVT_NORMAL,你好 Emitter,emitter.EventPriority.HIGH);this.addLog([post] EVT_NORMAL 已发送 HIGH);// LOW 优先级EmitterUtil.poststring(EVT_NORMAL,低优先级消息,emitter.EventPriority.LOW);this.addLog([post] EVT_NORMAL 已发送 LOW);什么时候用优先级优先级在消息队列有积压的时候生效。举个例子用户点击了一个按钮触发了一个 HIGH 优先级的 UI 更新事件同时后台有个 LOW 优先级的日志上报事件这时候系统会先处理 HIGH 的 UI 更新再处理 LOW 的日志上报保证用户操作的响应优先级。日常开发中的建议大多数情况下不需要手动指定优先级默认 LOW 就够用涉及 UI 更新、用户操作反馈的事件可以用 HIGH后台数据同步、日志记录之类的用 LOW 或者不指定不传优先级时的默认行为演示页里有一个按钮不带优先级参数// 不传优先级使用默认值EmitterUtil.poststring(EVT_ONCE,我只被消费一次);不传优先级时EmitterUtil 内部会使用一个默认值通常是 LOW。对于大多数业务场景这完全够用。实际项目中的类型设计建议基于演示代码给出几条实用建议1. 事件 ID 用常量统一管理// 事件 ID 常量constEVT_NORMALdemo_normal;constEVT_ONCEdemo_once;constEVT_PRIORITYdemo_priority;constEVT_TYPEDdemo_typed;不要在代码里散落大量魔法字符串。统一放在一个常量文件里改起来方便也不容易拼写错误。2. 每个事件只传一种类型的数据不要设计有时候传 string有时候传 number的事件这会让代码很难维护。一个事件 ID 对应一种固定的数据类型。3. 订阅中避免复杂逻辑事件回调应该尽量轻量复杂的业务逻辑放到单独的方法里// ✅ 推荐回调只做简单的调度EmitterUtil.onSubscribestring(EVT_NORMAL,(msg){this.onSubCount;this.addLog([onSubscribe] 第${this.onSubCount}次 →${msg});});写在最后泛型和优先级是 EmitterUtil 的两个锦上添花的特性泛型让事件数据有类型保障写代码更安全IDE 提示更友好优先级在高并发消息场景下控制处理顺序日常用默认值就行把这两篇结合起来EmitterUtil 的核心用法你已经掌握了。接下来就是在实际项目里多用多练。