uni.connectSocket 是唯一可靠入口,因其统一抽象各端底层 WebSocket API,而原生 new WebSocket() 在小程序和 App 端不可用,H5 使用会破坏跨端一致性。

uni-app 里不能用 new WebSocket(),必须用 uni.connectSocket —— 否则 App 和小程序端直接报错或静默失败。
为什么 uni.connectSocket 是唯一可靠入口
原生 WebSocket 构造函数在微信/支付宝小程序、iOS/Android App 环境中根本不可用;H5 虽能跑,但会破坏跨端一致性,上线后切到小程序就断连。uni-app 的 uni.connectSocket 是对各端底层 API(如微信的 wx.connectSocket、App 的原生 socket 封装)做的统一抽象,行为收敛、参数可控。
常见错误现象:
- 页面
onLoad中立刻调用uni.connectSocket→ App 端连接失败率高,因页面生命周期未就绪 - URL 写成
ws://→ 微信小程序强制校验,直接拒绝连接,控制台报invalid protocol - 带中文或特殊字符的查询参数没编码 → 如
?token=abc+def,+ 号被解析为空格,服务端鉴权失败,连接秒断
uni.connectSocket 必传参数与避坑细节
必须显式传 url,且协议只能是 wss://(小程序硬性要求),H5 开发调试可临时用 ws://,但上线前务必改回 wss://。
参数建议写法:
-
url:拼接前对所有查询参数做encodeURIComponent,例如wss://api.example.com?token=${encodeURIComponent(token)} -
header:小程序仅支持content-type和少数字段,X-Token类自定义头会被忽略,应改用 query 参数传递鉴权信息 -
success回调只表示“发起连接请求成功”,不等于已连上;真正连通要等uni.onSocketOpen触发 - 不要在
success里直接调socketTask.send→ 此时通道未就绪,大概率报fail websocket not connected
消息收发与状态管理的关键时机
收发消息不是“连上就能用”,必须严格按事件流推进:
- 发送第一条消息,必须放在
uni.onSocketOpen回调内,而非uni.connectSocket的success -
uni.onSocketMessage收到的event.data类型不固定:服务端发文本时是String,发二进制时是ArrayBuffer,需自行判断并转码(如new TextDecoder().decode(event.data)) - 页面跳转时,
uni.onSocketClose和uni.onSocketError的监听器不会自动解绑,若在多个页面重复注册,会导致回调触发多次 - App 端存在单实例限制:多个页面分别调
uni.connectSocket,底层实际只维持一个连接,后建覆盖先建,消息可能串到错误页面
多页面共用连接的最小可行方案
避免每个页面都新建连接,最简方式是全局单例 + 手动路由分发:
- 在
main.js或 Pinia store 初始化一个连接实例,由uni.onSocketOpen/uni.onSocketMessage统一监听 - 各页面通过事件总线(如
uni.$emit/uni.$on)或 store 订阅自己关心的消息类型 - 连接断开后,重连逻辑只在 store 内触发一次,不随页面切换重复执行
- 主动关闭连接时,必须调用
socketTask.close(),否则 App 端后台进程可能持续占用 socket 资源
真正难的不是连上,而是让连接在页面跳转、App 切后台、弱网抖动这些真实场景下不丢状态、不串消息、不重复初始化——这些细节没处理好,多端表现就会不一致。


















