uni-app发心跳包需手动管理WebSocket连接,设30–45秒间隔、检查readyState、前后台生命周期中正确开关连接,并统一JSON字符串格式收发,结合响应校验与后端推送判定真实在线状态。

uni-app 里怎么发心跳包不被后台断连
心跳包不是发得越勤越好,关键是让后端能识别、客户端能扛住。uni-app 没有原生 WebSocket 长连接的自动重连兜底,uni.connectSocket 断了不会自己续,必须手动管。
常见错误现象:onClose 触发后没重连,或重连逻辑写在 onError 里但没判空,导致无限报错;还有人在 onHide 时没关 socket,切后台后还在发请求,被系统 kill 或耗电飙升。
- 心跳间隔建议设为 30–45 秒,比后端超时阈值(如 60s)短 10–20 秒,留出网络抖动余量
- 用
setInterval发心跳前,先检查socketTask.readyState === 1,否则直接跳过 -
onHide里调用socketTask.close(),onShow里重新uni.connectSocket并重置心跳定时器 - 首次连接失败不要立刻重试,加个 1–3 秒退避延迟,避免雪崩式重连
uni-app 心跳数据格式怎么和后端对齐
很多问题其实卡在「双方说的不是同一种心跳语言」:后端要的是纯文本 {"type":"ping"},你发了个带 header 的 JSON 字符串但没 JSON.stringify;或者后端期待二进制 0x01,你却发了字符串 "ping"。
使用场景:微信小程序、App、H5 三端共用同一套 socket 逻辑时,H5 的 WebSocket 和 uni-app 的 uni.sendSocketMessage 对数据类型处理不一致。
- 统一用字符串发送,且始终
JSON.stringify({ type: 'ping', ts: Date.now() }),别传对象 - 后端返回心跳响应也必须是明确可 parse 的 JSON,比如
{"type":"pong","ts":171xxxxxx},前端收到后校验type === 'pong'再算一次有效心跳 - H5 端若用原生
WebSocket,注意它不支持ArrayBuffer以外的二进制发送,而uni.sendSocketMessage默认接受String或ArrayBuffer,混用容易丢包
用户在线状态怎么在页面里实时更新
不能靠「有没有心跳成功」就判断在线——网络延迟、短暂抖动都会导致单次心跳失败,但用户其实还在线。真正可用的状态,得结合心跳响应 + 最后活跃时间 + 后端主动推送的 user_offline 事件。
性能影响:每个页面都监听 uni.onSocketMessage 会导致重复绑定;用全局状态管理(如 Pinia / Vuex)存 isOnline,但没做防抖,频繁触发 setState 会卡 UI。
- 只在 App.vue 或 store 初始化时绑定一次
uni.onSocketMessage,用switch (res.data.type)分发事件,而不是每个页面都绑 - 定义一个
lastHeartbeatTime变量,每次收到pong就更新;另起一个setInterval每 5 秒检查Date.now() - lastHeartbeatTime > 60000,超时才设为离线 - 后端推送
{"type":"user_offline","uid":"xxx"}时,立刻置isOnline = false,不等心跳超时——这是唯一能确认「真掉线」的信号
App 打包后心跳失效的几个硬坑
开发时好好的,一打包成 iOS/Android 就连不上、收不到消息、心跳定时器莫名停掉。不是代码问题,是平台限制和配置漏项。
常见错误现象:uni.connectSocket 返回 success 但实际没建连;iOS 上切后台 30 秒后 socket 被系统 suspend;Android 某些厂商把后台进程干掉,心跳定时器直接消失。
- 检查
manifest.json里的「SDK 配置」:iOS 必须勾选「后台音频播放」或「后台定位」(哪怕不用),否则系统禁止后台 socket 活动;Android 要开「自启动」和「电池优化忽略」提示(需用户手动授权) - 不要依赖
setInterval在后台持续运行,App 切后台后 JS 线程会被冻结(尤其 iOS)。改用后端下发的push唤醒(如个推、华为 HMS)做离线保活,心跳只在前台活跃时维持 - 真机调试务必用正式域名(HTTPS/WSS),本地
ws://localhost在打包后一律失败,且证书错误不会抛onError,只会静默断连
最复杂的地方不在怎么发心跳,而在怎么定义「在线」——它从来不是二值的,而是分层的:网络层连得上、协议层认得清、业务层看得见。少一层,状态就失真一次。

















