Uni-app 中不能直接使用 new WebSocket(),因其跨端机制未透出 Web 标准 WebSocket 对象;App 和小程序端必须使用 uni.connectSocket 等封装 API 才能可靠通信。

Uni-app 里不能直接用原生 WebSocket 构造函数,必须走 uni.connectSocket 及配套 API,否则在 App 或小程序端会静默失败。
为什么 new WebSocket() 在 Uni-app 里不工作
Uni-app 的跨端机制决定了它不会把 Web 标准的 WebSocket 对象透出到 App(iOS/Android)和小程序环境。H5 端虽能运行,但一旦你打包成 App 或微信小程序,new WebSocket('wss://...') 会直接报错或无响应——常见错误是 TypeError: WebSocket is not a constructor 或连接后收不到 onmessage。
真正跨端可用的只有 uni.connectSocket 这套封装 API,它底层在各端调用对应原生能力(如 iOS 的 NSURLSessionWebSocketTask、Android 的 OkHttp WebSocket、小程序的 wx.connectSocket)。
- 只在 H5 环境下
new WebSocket()才有效;其他平台必须用uni.*Socket系列 -
uni.connectSocket返回的是Promise,不是实例对象,后续操作靠事件监听 - 连接成功后,
uni.onSocketOpen和uni.onSocketMessage必须在uni.connectSocket调用前注册,否则可能丢掉首条消息
uni.connectSocket 的正确调用顺序和必要监听
顺序错了,连接就不可靠。尤其注意:监听注册必须早于发起连接,且不能写在 then 里。
uni.onSocketOpen(() => {
console.log('socket 已连接')
})
uni.onSocketError((err) => {
console.error('socket 错误', err)
})
uni.onSocketMessage((res) => {
console.log('收到消息', res.data) // 注意:res.data 是 string,不是 JSON 对象
})
uni.onSocketClose(() => {
console.log('socket 已关闭')
})
// 此时再发起连接
uni.connectSocket({
url: 'wss://your-api.com/ws',
// 如果需要 token 鉴权,只能拼在 URL 后(如 ?token=xxx),不能传 headers(App 和小程序不支持)
}).catch(err => {
console.error('连接失败', err)
})
- 所有
uni.onSocket*必须全局注册(比如放在main.js或store初始化逻辑中),不要在页面onLoad里重复注册,否则可能监听多次或漏注册 -
url必须是合法的wss://(App/小程序强制要求 TLS)或ws://(仅 H5 开发时可临时用,上线必须 wss) - 小程序要求域名必须在后台配置「socket 合法域名」,否则直接拒绝连接,错误信息为
fail net::ERR_CONNECTION_REFUSED或更模糊的fail
发送消息、重连与心跳的实操要点
发送用 uni.sendSocketMessage,但它不返回 Promise,也不抛异常——失败时只会触发 uni.onSocketError。所以必须自己加状态兜底。
- 发消息前先检查
uni.getSocketState().connected === true,否则直接丢弃或进重试队列 - 重连不能用
setTimeout堆递归,建议用指数退避(如 1s → 2s → 4s → 8s),并在第 5 次失败后提示用户「网络异常,请稍后重试」 - 心跳必须由客户端主动发(服务端一般不推 ping),推荐每 30 秒
uni.sendSocketMessage({ data: 'ping' }),服务端回'pong';若连续两次没收到 pong,就断开并重连 -
uni.closeSocket调用后,会触发uni.onSocketClose,但不会自动清除已注册的监听——需手动调用uni.offSocket*避免内存泄漏(尤其在页面卸载时)
App 端后台断连和冷启动恢复问题
Android/iOS App 切后台超过几十秒,系统可能回收 socket 连接,且不会通知前端。用户切回来时,uni.getSocketState() 仍返回 { connected: true },但实际已断——这是最隐蔽的坑。
解决方法只有一个:**所有关键业务消息都带服务端时间戳 + 客户端本地缓存 lastActive 时间,每次收消息更新;如果 60 秒内没收到任何消息,主动发心跳并检查响应。没响应就 close + reconnect。**
- 不要依赖
onHide/onShow做连接管理——App 后台时这些生命周期不一定触发 - 冷启动(App 杀进程重启)后,必须在首页或登录后立即重建 socket,不能等用户点进某个聊天页才连
- 微信小程序在切后台 5 分钟后会自动断连,且
onSocketClose不一定触发,得靠定时心跳探测
跨端 WebSocket 最难的不是连上,而是让断连感知变得可靠。别信 connected 字段,多用心跳+时间戳交叉验证;别省那几行 offSocket*,页面销毁时漏掉监听,下次打开就收双份消息。


















