当前位置: 首页 > article >正文

OpenClaw08_监听器

OpenClaw08_监听器针对中文版本openClaw进行源码阅读当前项目针对【TypeScript中监听器】逻辑进行解读文章目录OpenClaw08_监听器1-参考地址2-知识整理3-动手实操1-TypeScript中监听器-源码部分2-TypeScript中监听器-简化版本如何测试方式一在线运行最快30秒方式二本地运行1-参考地址github版本OpenClawCNgitee版本OpenClawCNmac进行openclaw卸载参考openClaw源码拆解系列2-知识整理1OpenClaw源码-TypeScript中监听器-源码部分心跳极值2OpenClaw源码-TypeScript中监听器-简化版本3-动手实操1-TypeScript中监听器-源码部分// 心跳指示器类型定义用于 UI 层面展示不同的状态反馈// ok: 正常alert: 告警/发送中error: 错误exporttypeHeartbeatIndicatorTypeok|alert|error;// 心跳事件数据负载结构体封装了心跳请求与响应的核心信息exporttypeHeartbeatEventPayload{ts:number;status:sent|ok-empty|ok-token|skipped|failed;to?:string;preview?:string;durationMs?:number;hasMedia?:boolean;reason?:string;/** 心跳检测经由的通信通道名称。 */channel?:string;/** 标记消息是否被静默处理未触发 ShowOk 提示。 */silent?:boolean;/** 对应 UI 组件展示的指示器类型。 */indicatorType?:HeartbeatIndicatorType;/** 在多账户场景下区分归属的账户 ID。 */accountId?:string;};// 解析心跳事件状态码将其转换为对应的 UI 显示指示器类型// 参数status - 心跳事件的具体状态描述// 返回值对应的 IndicatorType 枚举值如果是 skipped 则返回 undefinedexportfunctionresolveIndicatorType(status:HeartbeatEventPayload[status],):HeartbeatIndicatorType|undefined{switch(status){// 空包成功或 Token 验证成功后视为正常状态caseok-empty:caseok-token:returnok;// 发送中通常作为告警提示展示告知用户正在处理casesent:returnalert;// 连接或请求失败时标识为错误状态casefailed:returnerror;// 跳过的步骤不产生具体的 UI 指示caseskipped:returnundefined;}}// 全局变量缓存最近一次发出的心跳事件数据用于后续查询letlastHeartbeat:HeartbeatEventPayload|nullnull;// 全局变量维护一个集合存储所有监听心跳事件的回调函数constlistenersnewSet(evt:HeartbeatEventPayload)void();// 发射心跳事件逻辑包含自动填充时间和分发通知// 参数evt - 待发送的心跳基础数据对象不含时间戳// 业务逻辑生成完整时间戳更新本地缓存遍历并调用所有订阅者exportfunctionemitHeartbeatEvent(evt:OmitHeartbeatEventPayload,ts){// 将当前系统时间与传入事件合并形成完整的事件负载constenriched:HeartbeatEventPayload{ts:Date.now(),...evt};// 保存最新的心跳快照到全局上下文lastHeartbeatenriched;// 依次通知所有已注册的监听器for(constlisteneroflisteners){try{listener(enriched);}catch{// 捕获单个监听器可能抛出的异常确保不影响其他监听器的执行/* ignore */}}}// 注册心跳事件监听器// 参数listener - 当事件发生时将被执行的回调函数// 返回值返回一个取消订阅函数调用它可从监听列表中移除当前回调exportfunctiononHeartbeatEvent(listener:(evt:HeartbeatEventPayload)void):()void{listeners.add(listener);// 返回清理函数实现类似 React useEffect 的 cleanup 模式return()listeners.delete(listener);}// 获取系统内部记录的最后一个心跳事件快照// 返回值若曾有过心跳发射则返回 Payload 对象否则返回 nullexportfunctiongetLastHeartbeatEvent():HeartbeatEventPayload|null{returnlastHeartbeat;}2-TypeScript中监听器-简化版本// // 极简事件总线 - 感受 TS 函数即值的语法// // 1. 【核心】定义一个存函数的盒子// 注意这里直接存的是 (n: number) void 这个函数类型constcallbacksnewSet(n:number)void();// 2. 【订阅】把函数塞进盒子functionsubscribe(fn:(n:number)void):()void{callbacks.add(fn);console.log( 订阅成功当前共${callbacks.size}个监听者);// 返回取消订阅函数也是一个函数return(){callbacks.delete(fn);console.log( 取消订阅剩余${callbacks.size}个);};}// 3. 【广播】遍历盒子挨个调用存的函数functionbroadcast(value:number):void{console.log(\n 广播数字:${value});for(constfnofcallbacks){fn(value);// ← 这就是 Java 做不到的直接括号调用}}// // 测试代码// console.log( 测试开始 \n);// 测试1创建3个不同的函数像创建3个变量一样简单constlistenerA(n:number)console.log([A] 收到:${n}平方是${n*n});constlistenerB(n:number)console.log([B] 收到:${n}翻倍是${n*2});constlistenerC(n:number)console.log([C] 收到:${n}我是来捣乱的 );// 测试2订阅把函数值存进 SetconstunsubscribeAsubscribe(listenerA);constunsubscribeBsubscribe(listenerB);subscribe(listenerC);// 这个不保存取消函数就永远无法移除了 // 测试3广播broadcast(10);// 测试4取消 A 的订阅再广播console.log(\n--- 取消 A 的订阅 ---);unsubscribeA();broadcast(5);// 测试5取消 B 的订阅再广播只剩 C 了console.log(\n--- 取消 B 的订阅 ---);unsubscribeB();broadcast(99);console.log(\n 测试结束 );日志打印[LOG]: 测试开始 [LOG]: 订阅成功当前共 1 个监听者[LOG]: 订阅成功当前共 2 个监听者[LOG]: 订阅成功当前共 3 个监听者[LOG]: 广播数字: 10[LOG]: [A] 收到: 10平方是 100[LOG]: [B] 收到: 10翻倍是 20[LOG]: [C] 收到: 10我是来捣乱的 [LOG]: --- 取消 A 的订阅 ---[LOG]: 取消订阅剩余 2 个[LOG]: 广播数字: 5[LOG]: [B] 收到: 5翻倍是 10[LOG]: [C] 收到: 5我是来捣乱的 [LOG]: --- 取消 B 的订阅 ---[LOG]: 取消订阅剩余 1 个[LOG]: 广播数字: 99[LOG]: [C] 收到: 99我是来捣乱的 [LOG]: 测试结束 [LOG]: 测试开始 [LOG]: 订阅成功当前共 1 个监听者[LOG]: 订阅成功当前共 2 个监听者[LOG]: 订阅成功当前共 3 个监听者[LOG]: 广播数字: 10[LOG]: [A] 收到: 10平方是 100[LOG]: [B] 收到: 10翻倍是 20[LOG]: [C] 收到: 10我是来捣乱的 [LOG]:--- 取消 A 的订阅 ---[LOG]: 取消订阅剩余 2 个[LOG]: 广播数字: 5[LOG]: [B] 收到: 5翻倍是 10[LOG]: [C] 收到: 5我是来捣乱的 [LOG]:--- 取消 B 的订阅 ---[LOG]: 取消订阅剩余 1 个[LOG]: 广播数字: 99[LOG]: [C] 收到: 99我是来捣乱的 [LOG]: 测试结束 [LOG]: 测试开始 [LOG]: 订阅成功当前共 1 个监听者[LOG]: 订阅成功当前共 2 个监听者[LOG]: 订阅成功当前共 3 个监听者[LOG]: 广播数字: 10[LOG]: [A] 收到: 10平方是 100[LOG]: [B] 收到: 10翻倍是 20[LOG]: [C] 收到: 10我是来捣乱的 [LOG]: --- 取消 A 的订阅 ---[LOG]: 取消订阅剩余 2 个[LOG]: 广播数字: 5[LOG]: [B] 收到: 5翻倍是 10[LOG]: [C] 收到: 5我是来捣乱的 [LOG]: --- 取消 B 的订阅 ---[LOG]: 取消订阅剩余 1 个[LOG]: 广播数字: 99[LOG]: [C] 收到: 99我是来捣乱的 [LOG]: 测试结束 [LOG]: 测试开始 [LOG]: 订阅成功当前共 1 个监听者[LOG]: 订阅成功当前共 2 个监听者[LOG]: 订阅成功当前共 3 个监听者[LOG]: 广播数字: 10[LOG]: [A] 收到: 10平方是 100[LOG]: [B] 收到: 10翻倍是 20[LOG]: [C] 收到: 10我是来捣乱的 [LOG]: --- 取消 A 的订阅 ---[LOG]: 取消订阅剩余 2 个[LOG]: 广播数字: 5[LOG]: [B] 收到: 5翻倍是 10[LOG]: [C] 收到: 5我是来捣乱的 [LOG]: --- 取消 B 的订阅 ---[LOG]: 取消订阅剩余 1 个[LOG]: 广播数字: 99[LOG]: [C] 收到: 99我是来捣乱的 [LOG]: 测试结束 [LOG]: 测试开始 [LOG]: 订阅成功当前共 1 个监听者[LOG]: 订阅成功当前共 2 个监听者[LOG]: 订阅成功当前共 3 个监听者[LOG]: 广播数字: 10[LOG]: [A] 收到: 10平方是 100[LOG]: [B] 收到: 10翻倍是 20[LOG]: [C] 收到: 10我是来捣乱的 [LOG]: --- 取消 A 的订阅 ---[LOG]: 取消订阅剩余 2 个[LOG]: 广播数字: 5[LOG]: [B] 收到: 5翻倍是 10[LOG]: [C] 收到: 5我是来捣乱的 [LOG]: --- 取消 B 的订阅 ---[LOG]: 取消订阅剩余 1 个[LOG]: 广播数字: 99[LOG]: [C] 收到: 99我是来捣乱的 [LOG]: 测试结束 [LOG]: 测试开始 [LOG]: 订阅成功当前共 1 个监听者[LOG]: 订阅成功当前共 2 个监听者[LOG]: 订阅成功当前共 3 个监听者[LOG]: 广播数字: 10[LOG]: [A] 收到: 10平方是 100[LOG]: [B] 收到: 10翻倍是 20[LOG]: [C] 收到: 10我是来捣乱的 [LOG]: --- 取消 A 的订阅 ---[LOG]: 取消订阅剩余 2 个[LOG]: 广播数字: 5[LOG]: [B] 收到: 5翻倍是 10[LOG]: [C] 收到: 5我是来捣乱的 [LOG]: --- 取消 B 的订阅 ---[LOG]: 取消订阅剩余 1 个[LOG]: 广播数字: 99[LOG]: [C] 收到: 99我是来捣乱的 [LOG]: 测试结束 如何测试方式一在线运行最快30秒打开 TypeScript Playground把上面代码全选复制进去按CtrlEnter或点击Run按钮看右侧 Console 输出方式二本地运行# 1. 创建文件mkdirts-democdts-democatdemo.tsEOF [把上面代码粘贴到这里] EOF# 2. 初始化并运行npminit-ynpminstallts-node typescript --save-dev npx ts-node demo.ts

相关文章:

OpenClaw08_监听器

OpenClaw08_监听器 针对中文版本openClaw进行源码阅读,当前项目针对【TypeScript中监听器】逻辑进行解读 文章目录OpenClaw08_监听器1-参考地址2-知识整理3-动手实操1-TypeScript中监听器-源码部分2-TypeScript中监听器-简化版本如何测试方式一:在线运行…...

ssm+java2026年毕设失踪儿童信息平台【源码+论文】

本系统(程序源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容一、选题背景关于失踪儿童问题的研究,现有研究主要以法律法规完善、打击拐卖犯罪、DNA数据库建设等宏观层面为主,专…...

Ollama不只是聊天机器人:解锁bge-m3的嵌入能力,5分钟搭建你的本地语义搜索Demo

Ollama不只是聊天机器人:解锁bge-m3的嵌入能力,5分钟搭建你的本地语义搜索Demo 当你第一次接触Ollama时,可能只是把它当作一个运行大语言模型的工具——输入问题,获取回答。但今天,我要带你重新认识这个被低估的瑞士军…...

极客玩法:OpenClaw+GLM-4.7-Flash控制智能家居

极客玩法:OpenClawGLM-4.7-Flash控制智能家居 1. 为什么选择这个组合? 去年装修新房时,我给自己定了个小目标:用最轻量的技术方案实现全屋智能控制。试过HomeAssistant原生语音模块和各类商业方案后,最终选择了OpenC…...

降低90%资产流失率:Snipe-IT开源解决方案的全生命周期管理创新方法

降低90%资产流失率:Snipe-IT开源解决方案的全生命周期管理创新方法 【免费下载链接】snipe-it A free open source IT asset/license management system 项目地址: https://gitcode.com/GitHub_Trending/sn/snipe-it 在数字化转型加速的今天,企业…...

Pixel Dimension Fissioner实战落地:政务公开文案亲和力提升裂变方案

Pixel Dimension Fissioner实战落地:政务公开文案亲和力提升裂变方案 1. 政务公开文案的挑战与机遇 政务公开文案长期以来面临着两大核心挑战:专业性与亲和力之间的平衡难题。传统政务文本往往过于严肃刻板,导致公众阅读意愿低、理解成本高…...

ColorsUtils嵌入式RGB色彩处理库深度解析

1. ColorsUtils库深度解析:嵌入式RGB色彩处理的工程实践指南1.1 库定位与工程价值ColorsUtils是一个面向Arduino平台的轻量级色彩工具库,其核心价值在于为资源受限的嵌入式系统提供高效、可移植的RGB色彩处理能力。在LED驱动、TFT显示、环境光识别、色彩…...

LongCat-Image-Edit V2案例分享:如何用一句话给图片换主体、加文字

LongCat-Image-Edit V2案例分享:如何用一句话给图片换主体、加文字 1. 引言:一句话改图的魅力 想象一下这样的场景:你手头有一张完美的风景照,但照片中的主体不够突出;或者你精心设计的海报只差最后一步——添加几个…...

BGE Reranker-v2-m3模型压缩技术:减小部署体积50%

BGE Reranker-v2-m3模型压缩技术:减小部署体积50% 如果你正在为RAG系统寻找一个既轻量又高效的重排序模型,那么BGE Reranker-v2-m3绝对值得你关注。这个模型最大的特点就是“小”——参数只有5.68亿,但性能却相当能打。 不过,在…...

uECC:超轻量级嵌入式ECC密码库实战指南

1. uECC:面向资源受限嵌入式系统的轻量级椭圆曲线密码学实现uECC(micro-ECC)是一个专为深度嵌入式环境设计的极简椭圆曲线密码学(ECC)库。它不依赖标准C库、不使用动态内存分配、无浮点运算、无递归调用,全…...

性能测试有哪些?

一、按测试目的与策略分类1.负载测试定义:模拟系统在预期正常workload下的表现。逐步增加并发用户数或数据量,观察系统性能指标(响应时间、吞吐量、资源利用率)是否满足预设的“性能阈值”。目的:验证系统在生产环境预…...

架构演进之 DDD:从 CRUD 到领域驱动设计

前言:每一个贫血模型背后,都有一个渐行渐远的业务在软件开发的早期阶段,我们通常从一个简单的 CRUD 应用开始。随着业务逻辑日益复杂,代码库逐渐膨胀,我们开始面临一个普遍的问题:业务逻辑散落在各处&#…...

003 TimeTagger 时间跟踪工具本地部署与开机自启

TimeTagger 本地部署与开机自启手册 一、TimeTagger 产品介绍 TimeTagger 是一款轻量级、开源免费的Web端时间跟踪工具,基于PythonWeb技术开发,支持本地离线运行、时间记录分类、数据统计分析,无需云端账号即可实现数据本地持久化存储&#…...

HMC5883L磁力计驱动开发与航向解算实战

1. HMC5883L电子罗盘芯片技术解析与嵌入式驱动开发实践HMC5883L是由Honeywell公司推出的三轴磁力计(Magnetometer),专为高精度地磁方向检测而设计。尽管其已逐步被更新型号(如QMC5883L、AK09916等)替代,但在…...

别再暴力删括号了:一道“删除无效括号”,看懂搜索本质与剪枝思维

别再暴力删括号了:一道“删除无效括号”,看懂搜索本质与剪枝思维 大家好,我是Echo_Wish。 今天聊一道很多人“看着简单,写起来崩溃”的经典题—— 👉 删除无效的括号(Remove Invalid Parentheses) 这题我第一次做的时候,说实话,脑子里只有一个想法: 👉 “不就…...

Audio Pixel Studio新手指南:MP3/WAV/OGG多格式兼容性测试与编码建议

Audio Pixel Studio新手指南:MP3/WAV/OGG多格式兼容性测试与编码建议 1. 认识Audio Pixel Studio Audio Pixel Studio是一款基于Streamlit开发的轻量级音频处理Web应用,专为需要快速处理音频内容的创作者设计。它集成了两大核心功能:Edge-T…...

BBDown:告别在线观看限制,打造你的专属B站离线视频库

BBDown:告别在线观看限制,打造你的专属B站离线视频库 【免费下载链接】BBDown Bilibili Downloader. 一款命令行式哔哩哔哩下载器. 项目地址: https://gitcode.com/gh_mirrors/bb/BBDown 你是否曾经遇到过这样的情况:想要收藏B站上的精…...

Java集合入门必看:ArrayList与LinkedList常用方法详解(附实战案例)

在Java开发中,集合是日常使用频率极高的工具,而ArrayList和LinkedList作为List接口的两大核心实现类,分别适用于不同的业务场景。很多初学者在使用时,常常混淆两者的方法用法,不清楚何时该用ArrayList、何时该用Linked…...

本地大模型系列:2.通过API让本地大模型为你服务

上一篇我们介绍了ollama和lmstudio,这两个工具都是个人版的运行大模型的工具,可以用来运行本地小参数的LLM(所谓小参数一般指不超过27B的4bit量化LLM,按照1B参与大约需要0.7G显存加载进行预测,加上其他开销月1-1.5G&am…...

Spring AI Alibaba MCP协议实战:模型上下文协议集成与工具调用

Spring AI Alibaba MCP协议实战:模型上下文协议集成与工具调用 导读:MCP(Model Context Protocol,模型上下文协议)是 Anthropic 于 2024 年末发布的开放标准,旨在解决 AI 工具调用的碎片化问题。Spring AI …...

嵌入式信号发生器库:高精度方波生成与载波调制

1. SignalGenerator 库概述SignalGenerator 是一个轻量级、可移植的嵌入式信号发生器开源库,专为资源受限的微控制器设计。其核心目标是在任意 GPIO 引脚上生成高精度、可编程的方波信号,同时支持载波调制(Carrier Modulation)功能…...

XPath 语法完全指南:从基础语法到 SQL 注入中的应用

爬虫、处理过配置文件、或者接触过 MySQL 的 XML 函数的一定都见过 XPath 这个名词。它是一种专门用来在 XML 文档中“寻址”的语言,语法像文件路径一样直观。同时,XPath 是 Web 安全领域中 SQL 报错盲注中的关键角色。一、XPath 是什么?XPat…...

南北阁 Nanbeige 4.1-3B 企业应用方案:私有化部署+对话记忆管理+审计日志扩展接口

南北阁 Nanbeige 4.1-3B 企业应用方案:私有化部署对话记忆管理审计日志扩展接口 想在企业内部部署一个既智能又安全的对话AI吗?今天我们来聊聊如何基于南北阁 Nanbeige 4.1-3B 模型,打造一个功能完备的企业级对话应用。这个方案不仅支持纯本…...

保姆级教程:用Python+Robotics Toolbox搞定Panda机械臂的DH建模与正逆解(附避坑指南)

从零实现Panda机械臂运动学:Python Robotics Toolbox实战指南 机械臂控制是机器人领域的核心技术之一,而运动学建模则是实现精准控制的基础。本文将带您使用Python的Robotics Toolbox,一步步完成Franka Emika Panda机械臂的DH参数建模、正运动…...

【JSReverser-MCP】一句话逆向猿人学21题

近期听闻AI可以做逆向了,于是赶紧来试一试。 相关参考: vibe coding 氛围编程 Vibe coding 用 AI 做 JS 逆向食用教程 JSReverser-MCP 源:https://github.com/NoOne-hub/JSReverser-MCP 安装 环境要求 nodejs v22及以上 已部署Claude code或codex…...

GLM-TTS语音克隆实测:5分钟搞定方言克隆,效果惊艳!

GLM-TTS语音克隆实测:5分钟搞定方言克隆,效果惊艳! 1. 引言:语音克隆技术的新突破 在数字内容爆炸式增长的今天,个性化语音合成技术正成为内容创作者、企业客服、教育机构等领域的刚需。传统语音克隆方案往往需要数小…...

Adafruit ICM20X库详解:ICM20649与ICM20948驱动开发指南

1. 项目概述 Adafruit ICM20X 是 Adafruit 官方维护的 Arduino 兼容库,专为 TDK InvenSense 公司推出的 ICM20649 与 ICM20948 两款高性能 MEMS 运动传感器设计。该库并非通用型 ICM20X 系列驱动,而是聚焦于 Adafruit 自行设计并销售的硬件模块——即 I…...

计算机视觉进阶教学之Mediapipe库(一)

目录 简介 一、Mediapipe Python的安装和应用 二、手部检测 1. 导入必要的库 2. 初始化 MediaPipe 组件 3. 配置并创建手部检测模型实例 4. 启动摄像头并进入主循环 5. 绘制检测结果 三、手势识别 1. 手势识别核心逻辑 a. 计算基准距离 (Base Distance) b. 计算各手…...

Alpamayo-R1-10B开源模型价值:降低L4研发门槛,让算法团队专注因果逻辑而非工程胶水

Alpamayo-R1-10B开源模型价值:降低L4研发门槛,让算法团队专注因果逻辑而非工程胶水 1. 项目概述 Alpamayo-R1-10B是NVIDIA推出的自动驾驶专用开源视觉-语言-动作(VLA)模型,作为一套完整的自动驾驶研发工具链&#xf…...

SmolVLA参数详解:256×256输入分辨率对边缘计算设备的友好性分析

SmolVLA参数详解:256256输入分辨率对边缘计算设备的友好性分析 1. 引言:为什么边缘设备需要紧凑的视觉语言动作模型 在机器人技术和边缘计算领域,我们经常面临一个核心矛盾:强大的AI能力需要大量计算资源,而边缘设备…...