uni.connectsocket 是跨端 websocket 唯一入口,必须用 wss:// 协议、配置白名单、编码参数;onsocketopen 后才能发消息;收发数据需类型判断与 json 处理;断连重连须按平台特性实现指数退避策略。

uni.connectSocket 不是 new WebSocket 的跨端平替,而是必须用的唯一入口;连不上、收不到、发不出,90% 是协议、时机或类型判断没对齐。
uni.connectSocket 必须传 wss:// 且 manifest 配置白名单
小程序和 App 端强制校验协议与域名:ws://localhost 或 ws://192.168.x.x 在真机上根本不会触发 onSocketOpen,也不会报错,连接被静默丢弃。H5 能跑只是开发阶段的“假象”。
-
url必须是wss://开头,哪怕本地调试也得配反向代理(如 Nginx)转 wss - App 端需在
manifest.json→ “SDK 配置” → “WebSocket 合法域名”里填入域名(不带协议和路径) - 微信/支付宝小程序还要在后台配置“request 合法域名”,且必须已备案、已 HTTPS
- URL 中带查询参数(如
?token=abc+def)必须用encodeURIComponent编码,否则 App 端解析失败断连
onSocketOpen 触发后才能 send,且 data 必须是字符串
很多人在 uni.connectSocket 的 success 回调里直接调 sendSocketMessage,结果报 websocket not connected —— 这是因为连接通道尚未就绪,success 只表示发起请求成功,不是已连通。
- 发送首条消息必须等
uni.onSocketOpen回调执行完毕后再调用uni.sendSocketMessage -
uni.sendSocketMessage({ data: ... })的data参数只接受String或ArrayBuffer,传对象(如{type: 'login'})会静默失败 - 统一做法:发送前必做
JSON.stringify(),服务端按 JSON 解析
onSocketMessage 收到的数据类型不可控,不能无脑 JSON.parse
同一段代码,在 H5 可能收到 String,在 App 或小程序却收到 ArrayBuffer,直接 JSON.parse(res.data) 必然崩溃。
- 必须先判断:
typeof res.data === 'string'才走JSON.parse - 如果是
ArrayBuffer,用new TextDecoder().decode(res.data)转成字符串再解析 - 高并发下服务端连续发多条文本消息,App 端可能合并为一个
ArrayBuffer,也可能拆成两次回调 —— 别依赖“一次回调 = 一条消息”,需自行加分隔符或长度头做粘包处理
App 切后台后连接必断,重连策略不能简单轮询
iOS/Android 系统会在 App 进入后台 10–30 秒内强制回收 WebSocket 连接,这不是 bug,是系统行为。盲目 setInterval 重连只会耗电、被系统 kill、触发平台限频。
- 监听
uni.onSocketClose和uni.onSocketError,区分是主动关闭还是异常断开 - 重连前检查当前是否在前台:
uni.getBackgroundAudioPlayerState或监听页面onShow/onHide生命周期 - 采用指数退避(如 1s → 2s → 4s → 8s),并限制最大重试次数(如 5 次),避免雪崩
- 连接恢复后,优先同步未 ACK 的消息,而不是立刻发新消息
跨端 WebSocket 最难的从来不是“怎么连”,而是“什么时候算连上了”“收到的到底是什么”“断了之后该不该重、怎么重”。这些细节藏在各端底层实现里,不踩一遍坑很难意识到它们真实存在。











