小程序实时数据更新通常怎么做?轮询、WebSocket 和云数据库监听如何选择?
简化版
小程序实时更新可以用定时轮询、长连接 WebSocket、云数据库 watch 或服务端推送能力。选择时看实时性、连接成本、数据量、后台限制和一致性要求;低频状态用轮询,高实时双向通信用 WebSocket,云开发轻量场景可用数据库监听。
详细版
常见方案:
- 轮询:实现简单,适合订单状态、审核状态等低频变化。
- WebSocket:实时性好,适合聊天、协同、行情、设备状态。
- 云数据库监听:适合云开发体系内的数据变化订阅。
- 订阅消息:适合用户离开小程序后的服务触达,不适合页面内实时刷新。
关键注意点:
- 页面显示中才保持必要连接。
- 断线重连要有限退避。
- 消息要有序号、时间戳或版本号。
- 前端展示要能处理重复、乱序和延迟。
- 不要为了低频状态强上 WebSocket。
完整版教学
一、实时性不是只有一种等级
“实时更新”要先问业务能容忍多少延迟。订单支付结果可能 1 到 5 秒确认都可以;聊天消息希望 1 秒内到达;多人协同编辑则可能要求更低延迟和更严格的冲突处理。不同延迟目标对应完全不同的方案。
所以面试时不要直接回答“用 WebSocket”。更成熟的回答是先按实时性、双向性、并发连接数和数据频率分级,然后再选技术。
低实时:5s~30s 轮询
中实时:1s~5s 短轮询/数据库监听
高实时:毫秒~1s WebSocket
离线触达:订阅消息
二、轮询简单但要控制频率
轮询就是定时请求服务器查询最新状态。它的优点是实现简单、兼容性好、服务端无长连接压力;缺点是实时性有限,并且无变化时也会产生请求。
数字例子:10000 个在线用户每 3 秒轮询一次,QPS 约等于 10000 / 3 ≈ 3333。如果改成每 15 秒一次,QPS 约 667。对于订单状态这种低频变化,15 秒轮询加用户手动刷新可能更划算。
轮询 QPS ≈ 在线用户数 / 轮询间隔秒数
10000 / 3 ≈ 3333 QPS
三、WebSocket 适合双向和高频消息
WebSocket 建立长连接后,服务端可以主动推送消息,小程序端也可以发送消息。聊天、实时客服、设备状态、多人房间这类场景更适合它。它的成本在于连接管理、心跳、重连、鉴权和消息可靠性。
小程序端要在页面进入时连接,在页面隐藏或业务结束时按需关闭。服务端要识别用户身份,不能只相信前端传入的 userId。消息最好带 messageId 或 sequence,方便去重和乱序处理。
| 方案 | 优点 | 缺点 | 适合 |
|---|---|---|---|
| 轮询 | 简单稳定 | 请求浪费 | 订单状态 |
| WebSocket | 实时双向 | 连接治理复杂 | 聊天/协同 |
| 数据库监听 | 云开发集成好 | 平台绑定 | 轻量实时列表 |
| 订阅消息 | 离线触达 | 非页面实时 | 预约提醒 |
四、断线重连要有退避
移动网络切换、锁屏、页面切后台都可能导致连接断开。重连不能无限快速重试,否则会造成客户端耗电和服务端压力。常见做法是指数退避或阶梯退避,并在用户离开页面时停止。
例如第一次断开 1 秒后重连,第二次 2 秒,第三次 5 秒,最多尝试 5 次。用户重新进入页面或点击重试时再恢复。这样能在网络短抖动时自动恢复,也避免弱网下疯狂请求。
五、消息一致性要靠版本而不是感觉
实时消息可能重复、乱序或延迟。比如商品库存先收到版本 12 的“剩余 3 件”,后收到版本 11 的“剩余 5 件”,如果前端直接覆盖,就会显示旧数据。每条消息最好带版本号或更新时间,前端只接受更新的版本。
function applyMessage(msg) {
const current = state[msg.id]
if (!current || msg.version > current.version) {
state[msg.id] = msg
}
}
六、生命周期管理是小程序特色
小程序页面有显示、隐藏和卸载生命周期。实时连接如果不随生命周期清理,就可能在用户离开页面后仍然占用资源,或者回到页面时重复建立多个连接。实际代码要在 onShow、onHide、onUnload 中明确连接策略。
对聊天页面,可以页面显示时连接,隐藏短时间保留或关闭,卸载时清理监听;对订单结果页,可以短轮询到成功或超时后停止。不同页面不要共用一套无差别实时策略。
记忆钩子:实时方案先定延迟目标,再算连接和请求成本;别让“看起来高级”的 WebSocket 绑架简单业务。
七、常见误区与追问
- 误区:实时需求都应该用 WebSocket。 低频状态用轮询更简单可靠,WebSocket 适合高频双向场景。
- 误区:连接断了立即无限重连。 应使用有限次数和退避策略,并结合页面生命周期停止无意义重连。
- 误区:服务端推来的消息一定按顺序到。 网络和重连可能导致乱序,消息要带版本号或时间戳。
- 追问:订单支付结果怎么更新? 可用短轮询查询订单状态,成功或超时后停止;最终状态以后端为准。
- 追问:聊天消息如何去重? 每条消息带唯一 ID,前端和服务端都按 ID 做幂等处理。
- 追问:小程序切后台后连接怎么办? 按业务决定关闭或短暂保留,恢复时重新同步最新状态。
八、加强记忆
实时更新用“延迟目标、成本估算、生命周期、消息版本”来记。低频用轮询,高频双向用 WebSocket,云开发轻量场景可用监听,离线触达用订阅消息。无论哪种方案,都要处理断线、重复、乱序和页面隐藏,否则实时越做越不稳定。