WebSocket断开不触发onClose是因平台差异:微信小程序静默断连,H5受页面休眠影响;须主动心跳+自动重连,统一用时间戳判超时,按平台处理证书与网络状态。

uni-app里WebSocket断开后不触发onClose?先确认平台限制
微信小程序、支付宝小程序和App端对WebSocket的底层实现差异很大,尤其是微信小程序——它根本不会在后台或切页时触发onClose,而是直接静默断连。H5端虽能触发,但若页面被浏览器休眠(如标签页非激活状态),onClose也可能延迟数秒甚至不触发。所以不能只依赖onClose来判断连接失效。
实操建议:
- 所有平台都必须主动发心跳包,不能等断连再处理
- 微信小程序需额外监听
onHide/onShow,在onHide中手动close连接,避免残留无效实例 - App端(iOS/Android)要检查是否开启后台保活权限,否则系统可能强制回收WebSocket连接
怎么写一个带心跳和自动重连的uni.connectSocket封装
原生uni.connectSocket不提供重连逻辑,必须自己控制状态机。核心是:连接中定时发ping、收到pong就刷新心跳计时器、超时未响应就close并重试。
实操建议:
- 用
setTimeout而非setInterval做心跳,避免多个定时器叠加(重连时旧定时器未清除) - 心跳间隔设为30s,服务端
ping_timeout建议设为45s,留出网络抖动余量 - 重连次数限制为5次,第6次起指数退避(如1s → 2s → 4s → 8s),避免打爆服务端
- 每次重连前检查
uni.getNetworkType,无网络时不尝试,防止无效重试
示例关键逻辑片段:
let heartTimer = null;
let reconnectTimes = 0;
function startHeart() {
heartTimer = setTimeout(() => {
if (socketTask && socketTask.readyState === 1) {
socketTask.send({ data: '{"type":"ping"}' });
// 启动pong响应等待
setTimeout(() => {
if (!lastPongReceived) {
socketTask.close();
reconnect();
}
}, 5000);
}
}, 30000);
}
onMessage里收到"pong"却不更新心跳状态?检查JSON解析和字段匹配
很多开发者把服务端返回的{"type":"pong","ts":171...}直接当字符串比对=== "pong",结果永远不匹配。还有人没做JSON.parse就访问data.type,导致undefined报错中断后续逻辑。
实操建议:
- 统一约定服务端心跳响应格式为纯文本
"pong",或固定JSON结构{"op":"pong"},避免嵌套字段干扰 - 在
onMessage开头加try/catch,防止解析失败阻塞心跳流程 - 用
lastPongReceived = Date.now()标记时间戳,而不是布尔值,便于调试超时是否真发生 - H5端注意:某些CDN或代理会过滤掉
ping/pong帧,此时需改用业务层心跳(如{"cmd":"heartbeat"})
App端重连频繁失败?检查uni.getSystemInfo里的platform和证书配置
Android上uni.connectSocket若连wss://地址失败,大概率是SSL证书问题:自签名证书不被信任、证书链不全、或域名与证书CN不匹配。iOS更严格,还会校验OCSP Stapling状态。
实操建议:
- 用
uni.getSystemInfo确认platform是"ios"还是"android",不同平台错误码含义不同(如Android1006常是证书问题,iOS1005可能是协议不支持) - App端打包时,在
manifest.json的“SDK配置”里勾选“WebSocket”模块,并确保Android的minSdkVersion ≥ 21 - 测试阶段先用
ws://(非加密)验证逻辑是否正常,再切回wss://排查证书 - 若必须用自签证书,Android需在
nativeplugins中集成OkHttp并自定义TrustManager,iOS需在Info.plist加NSAppTransportSecurity例外(不推荐上线使用)
长连接稳定性的关键不在“连得上”,而在“断得清、重得准、判得早”。多数线上故障不是连不上,而是旧连接挂着不动、新连接又叠加上去,最后卡死在握手阶段或消息堆积。心跳和重连逻辑必须和连接生命周期强绑定,而不是独立运行。


















