更新记录

1.0.3(2026-10-20) 下载此版本

  • libs/stompClient.js:STOMP 协议帧日志改为无条件静默 —— CONNECT 帧含明文 login/passcode, 不再随 debug 开关打印;连接过程调试看 [uni-stomp] 的结构化日志即可
  • package.json:dcloudext.type 修正为 sdk-js(插件市场合规)
  • readme.md:debug 配置说明同步上述行为

1.0.2(2026-10-09) 下载此版本

修复:此前文档承诺但未真正生效的能力

  • unsubscribe(topic) 现在会真正下发 STOMP 注销并清理底层订阅缓存。此前只从上层数组里删除, 服务端订阅仍在,连接恢复时还会被重新订阅("复活")
  • parse(fn) 现在真正生效:订阅回调的入参先经过自定义解构器 (topic, payload) => any; 此前 _parser 定义并可设置,但订阅回调里从未调用它
  • heartbeat 配置真正生效:STOMP heart-beat 头按该值发送;此前硬编码为 20000
  • debug 默认改为 false;底层两处未受 debug 控制的日志(连接成功、每条消息内容)改为受控, 且默认不再打印消息体(降低日志噪音、避免消息内容外泄)
  • useMQBus() 改为顶层静态 import { onUnmounted } from 'vue'。此前用 require('vue') 且吞掉异常, 在 ESM 构建(H5)下自动清理会静默失效,页面反复进出会重复绑定监听

新增

  • connect() 返回 Promise(连上 resolve;首次失败或超时 reject),可 await;失败后底层仍按退避策略继续重连
  • 连接状态改为事件驱动(onConnected / onDisconnected / onError): 掉线时 getStatus() 会实时回到 false,意外断线也会通知;此前靠 200ms 轮询,掉线后状态不回退且无通知
  • 重连改为指数退避 + 抖动(±20%),可配 maxReconnectInterval / maxReconnectAttempts
  • 断线期间待发队列加上限 maxQueue(默认 200,超出丢弃最旧一条),此前无上限、长时间断线会无限堆积
  • 同一 topic 支持挂多个监听(Set 分发);此前第二个回调会被底层静默忽略
  • register() 返回注册表,并新增 start(key) / startAll() / stop(key):auto:false 的项可按需启动
  • 事件总线:on() / once() 返回取消句柄;新增 once()、listeners()、clear(name)
  • useMQBus() 额外返回 dispose(),可在组件外手动清理
  • 新增 getTopics() / getQueueLength()
  • libs/uniWebSocket.js 的 removeEventListener 改为按回调精确移除;此前用 pop(),注册多个监听时会移除错对象
  • 新增 license.md(含第三方协议声明)

其他

  • package.json:平台矩阵按实际支持填写(此前全为空,插件市场会显示成"不支持任何平台");标签精简为 5 个
  • config.js 改为通用示例模板(主题名不再是具体业务字符串);readme.md 全面重写,补充排障章节

1.0.1(2026-09-17) 下载此版本

修复打包告警:libs/stomp.js ... Error when using sourcemap for reporting an error: Can't resolve original location of error 该文件已是 ESM(顶层 this 恒为 undefined),移除文件末尾无意义的 }).call(this),同时删除 ESM 下永不执行的 CJS 分支(module.exports);运行行为不变。

查看更多

平台兼容性

uni-app(3.8.6)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
× √ √ √ √ × √ √ √
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
√ × × × × × × × × - × ×

yolo-mq STOMP 消息总线

基于 uni.connectSocket 的 STOMP over WebSocket 消息总线,内置事件总线、心跳、指数退避重连、断线消息补偿与页面级自动清理。

与具体业务无关:连接地址、订阅主题、消息格式全部由使用方决定。

平台支持

平台 支持 说明
App(Android / iOS / 鸿蒙) √ 直接使用 uni.connectSocket
H5 √ 浏览器 WebSocket
微信小程序 √ 需 wss:// 且在后台配置 socket 合法域名
其他小程序 × 未适配
uni-app x × 未适配

文件结构

yolo-mq/
├─ index.js        # 组合入口(MQ + EventBus),日常用这个
├─ core.js         # 连接核心:connect / subscribe / unsubscribe / parse
├─ eventBus.js     # 独立事件总线(可脱离 MQ 单独用)
├─ config.js       # 订阅配置模板(示例,可不用)
└─ libs/           # 内部实现,勿直接依赖(升级可能变动)
   ├─ stomp.js         # STOMP 协议实现(原样分发,Apache-2.0)
   ├─ stompClient.js   # 连接/订阅/队列/重连
   └─ uniWebSocket.js  # SocketTask 封装(多实例互不干扰)

稳定接口:index.js(默认导出)、core.js、eventBus.js、config.js 四个入口文件的导出; libs/ 下为内部实现,请勿直接 import(后续版本可能重构)。 uni_modules 规范里没有 js_sdk 这个强制目录 —— 纯 JS 插件放在插件根目录即可用 (若你更习惯 js_sdk 路径写法,可自行把文件挪进去,只要保证 import 路径一致)。

快速开始

// main.js
import mq from '@/uni_modules/yolo-mq'
uni.$mq = mq

// ① 可选:运行时配置
mq.config({
  debug: false,            // 日志开关,默认 false
  heartbeat: 20000,        // STOMP 心跳(ms)
  reconnectInterval: 5000, // 首次重连间隔,之后指数退避
  maxReconnectInterval: 60000,
  maxReconnectAttempts: 0, // 0 = 不限次数
  maxQueue: 200,           // 断线期间待发消息上限
  onConnected: () => { /* 已连接 */ },
  onDisconnected: () => { /* 断开(主动/被动都会触发) */ },
})

// ② 注册订阅(清单见下)
mq.register({
  NOTICE: { topic: '/topic/demo.notice', event: 'demo:notice', auto: true },
  CHAT:   { topic: '/queue/demo.chat',   event: 'demo:chat',   auto: false },
})

// ③ 连接(返回 Promise:连上 resolve,首次失败/超时 reject)
mq.connect('ws://192.168.1.10:61614', 'guest', 'guest')
  .then(() => console.log('已连接'))
  .catch(err => console.warn('首次连接未成功,仍在后台重连:', err.message))

// ④ 监听(事件名与订阅清单里的 event 对应)
uni.$mq.on('demo:notice', data => console.log('收到:', data))

// ⑤ 退出时断开
// mq.disconnect()

auto:false 的订阅项不会自动订阅,需要时手动启动:

mq.start('CHAT')
mq.stop('CHAT')     // 停止(可再次 start)
mq.startAll()       // 启动全部(含 auto:false)

运行时配置

配置项 类型 默认值 说明
debug Boolean false 打印 info/warn 日志(error 始终打印);底层协议帧日志(含明文 login/passcode)始终静默
connectTimeout Number 10000 首次连接超时(ms)
heartbeat Number 20000 STOMP 心跳间隔(ms,双向)
reconnectInterval Number 5000 首次重连间隔(ms)
maxReconnectInterval Number 60000 退避上限(ms)
maxReconnectAttempts Number 0 最大重连次数,0 = 不限
maxQueue Number 200 断线期间待发消息上限(条)
onConnected Function - 连接成功回调
onDisconnected Function - 断开回调(主动断开与被动断开都会触发)
onError Function - 连接异常回调

完整 API

连接

方法 说明 返回
config(opts) 运行时配置(见上表) 当前配置
connect(url, login?, passcode?) 连接 broker(http(s):// 会自动转 ws(s)://) Promise<{ url }>
disconnect() 主动断开:清空订阅缓存与待发队列,不再重连 Promise<void>
getStatus() 是否已连接(掉线实时回到 false) Boolean
getQueueLength() 断线期间积压的待发消息条数 Number

订阅

方法 说明 返回
subscribe(topic, eventName?) 订阅并转发到事件总线 取消句柄 { topic, cancel }
unsubscribe(topic) 取消该主题订阅(会真正下发注销) Boolean
getTopics() 当前订阅的主题列表 String[]
register(subs) 批量注册({ KEY: { topic, event, auto } }) 注册表
start(key) / startAll() / stop(key) 启动/停止注册项 订阅句柄 / 注册表 / Boolean
parse(fn) 自定义消息解构器 (topic, payload) => any,作用于订阅回调入参 -

事件总线

方法 说明
on(name, fn) 监听事件,返回取消句柄
once(name, fn) 只监听一次,返回取消句柄
off(name, [fn]) 移除指定回调 / 清空该事件
emit(name, data) 派发事件
useMQBus() 组件级监听,卸载自动清理

页面级监听(推荐)

<script setup>
import { onMounted } from 'vue'
import mq from '@/uni_modules/yolo-mq'

const { on, dispose } = mq.useMQBus()

// 组件卸载时自动清理;需提前清理时调 dispose()
on('demo:notice', data => console.log(data))
</script>

⚠️ useMQBus() 必须写在组件 setup 内,否则拿不到组件实例、无法自动清理(会打印提示)。

消息格式与自定义解析

订阅回调收到的是解析后的对象:

{ header: {...}, body: {...}, raw: 原始帧 }
  • 消息体是 JSON → body 为解析后的对象
  • 消息体形如 {头部JSON}|{正文JSON} → header / body 分别解析
  • 解析失败 → { error, body: 原始字符串, header: {}, raw }

想改成自己的结构,用 parse():

mq.parse((topic, payload) => {
  // payload 是默认解析结果,这里可任意改造
  return { topic, ...payload.body }
})

连接状态与重连

  • 重连策略:被动断开后按 min(reconnectInterval × 2^n, maxReconnectInterval) 退避,带 ±20% 抖动,避免网络恢复瞬间大量客户端同时重连
  • 订阅恢复:断开时缓存订阅,重连成功后由底层统一恢复(只此一处,不会重复订阅)
  • 消息补偿:未连接时 send 会入队(最多 maxQueue 条,超出丢最旧),连上后按序重发
  • 主动断开 与 被动断开 的区别:主动 disconnect() 会清空订阅缓存与待发队列、停止重连;被动断开只标记状态并重连

从 1.0.1 升级

1.0.2 的 API 向后兼容(只新增方法与回调,旧调用方式不变),但有 4 处行为变化需要留意:

变化 影响 建议
disconnect() 现在会清空订阅缓存与待发队列 若依赖「断开后重连能自动恢复订阅」,需在重连前重新注册订阅 流程保持「先 register() 再 connect()」即可
parse(fn) 由「无效」变为「生效」 若之前设置过它,订阅回调的入参结构会变成你返回的内容 用不到就删掉该调用
debug 默认由 true 改为 false 日志变少 排查时 mq.config({ debug: true })
connect() 现在返回 Promise 不等待不影响连接;失败时会被浏览器记为「未处理的 Promise 拒绝」 加 .catch(err => {}),或用 onError 统一处理

另外 1.0.1 中 unsubscribe()、heartbeat、parse() 实际是未生效的(详见 changelog.md),1.0.2 修正后行为才与文档一致。

排障

现象 排查方向
connect() 一直 reject / 超时 地址端口是否可达、是否需要 wss、账号密码是否正确;失败后底层仍在重连,可用 getStatus() 或 onConnected 观察
订阅了但收不到消息 确认 topic 与 broker 侧一致(/topic/ 广播 vs /queue/ 点对点);debug: true 看连接与订阅日志
同一事件被处理多次 检查是否重复 on()(用 useMQBus() 或保留 on() 返回的取消句柄);跨页面监听未清理也会累积
小程序连不上 必须 wss://,且已在平台后台配置 socket 合法域名
页面反复进出后回调变多 确认监听是在组件 setup 内通过 useMQBus() 注册(卸载自动清理)
断线期间发的消息丢了 检查 getQueueLength() 是否触顶(maxQueue),必要时调大上限

单独使用

// 只用连接核心
import mqCore from '@/uni_modules/yolo-mq/core'
mqCore.config({ debug: true })
await mqCore.connect('ws://host:61614', 'guest', 'guest')
const sub = mqCore.subscribe('/topic/demo.notice', payload => console.log(payload))
sub.cancel()
mqCore.disconnect()

// 只用事件总线(与 MQ 无关)
import bus from '@/uni_modules/yolo-mq/eventBus'
const cancel = bus.on('app:ready', () => {})
bus.emit('app:ready')
cancel()

// 订阅清单模板(示例,请替换成自己的主题)
import { SUBS } from '@/uni_modules/yolo-mq/config'

授权

免费插件,可自由用于商业与非商业项目。插件内 libs/stomp.js 为第三方开源实现(Apache-2.0), 请保留其版权头 —— 详见 license.md。

隐私、权限声明

1. 本插件需要申请的系统权限列表:

网络(WebSocket 连接)

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集任何数据,消息内容仅在你的设备与自建 broker 之间传输

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

无

许可协议

使用协议与第三方声明

本插件(yolo-mq)为免费插件,可自由用于商业与非商业项目。

第三方代码声明

插件内 libs/stomp.js 为 STOMP over WebSocket 协议实现的原样分发(仅做过 ESM 化处理,未改动协议逻辑),版权与协议如下:

  • Stomp Over WebSocket(stomp-websocket)
    • LICENSE: Apache License V2.0
    • Copyright (C) 2010-2013 Jeff Mesnil — http://jmesnil.net/
    • Copyright (C) 2012 FuseSource, Inc. — http://fusesource.com
    • 该文件内已保留原始版权与协议头,请勿删除或修改

使用要求

  1. 使用、分发本插件时,请保留第三方代码文件内的版权与协议头。
  2. 插件本身不采集任何用户数据;消息内容仅在你配置的 WebSocket 地址(mq.connect(url, ...))与你自己的 broker 之间传输。
  3. 小程序端需使用 wss:// 并在相应平台后台配置 socket 合法域名(平台限制,非插件行为)。