根本原因是状态管理缺失、重连无兜底、关闭未判空;应维护 socketstatus 状态枚举,onopen 设 open、onclose/onerror 设 closed,关闭前校验状态并清空引用。

调用 wx.connectSocket 后频繁报错,尤其是 closesocket:fail websocket is not connected 或 open fail: _code:1004,根本原因不是“连不上”,而是状态没管住、重连没兜底、关闭没判空——直接硬调 wx.closeSocket() 就会炸。
为什么 wx.closeSocket() 总报 “not connected” 错误
这个错误不是网络问题,是代码在连接还没建立成功(onOpen 没触发)或已经断开(onClose 已执行)时,仍调用了 wx.closeSocket()。小程序的 SocketTask 对象一旦失效,底层连接就不可操作,但 JS 层变量还挂着,容易误判。
- 常见触发点:页面
onUnload里无条件调wx.closeSocket(),但此时连接可能从未打开过 - 多页面共用一个 socket 实例时,A 页面关了连接,B 页面还在读
socketTask状态 - 未监听
onClose和onError,导致连接已断,但isConnected标志位没更新 -
wx.closeSocket()是异步的,且不返回 Promise,无法 await 等待真正关闭,后续逻辑可能立刻执行并再次调用
如何安全调用 wx.closeSocket()
必须加两层防护:先查连接状态,再确保只关一次。
- 不要依赖
socketTask是否为 null,而要检查其readyState—— 但注意:小程序里socketTask.readyState不稳定,建议自己维护状态枚举SocketStatus - 在
onOpen回调中把状态设为OPEN,在onClose和onError中设为CLOSED - 封装关闭方法,加 guard:
close() { if (this.status !== SocketStatus.OPEN && this.status !== SocketStatus.CONNECTING) return; this.status = SocketStatus.CLOSING; wx.closeSocket(); } - 调用后立即清空
socketTask引用,并停止心跳定时器(如果已启动)
wx.connectSocket 失败的真凶常藏在 header 和 protocols
真机报 errCode: 1004、TLS handshake failed 或 invalid http status,90% 和服务端反向代理或跨域配置有关,和小程序代码关系不大。
-
header字段在wx.connectSocket中基本无效(小程序不透传),别白费劲填Authorization或Cookie -
protocols必须和服务端声明的 subprotocol 完全一致,大小写敏感;若服务端没配,就别传,传了反而 400 - 服务器 Nginx 配置必须含关键三行:
proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";
- 域名必须在微信后台「开发管理 → 域名信息」中加入
wss白名单,缺一不可
自动重连不能靠 setTimeout 堆,得控节奏
简单 setTimeout(() => wx.connectSocket(), 1000) 会雪崩:弱网下反复建连失败,触发大量 onError,最终耗尽系统资源或被微信限流。
- 用指数退避:首次重试 1s,失败则 2s → 4s → 8s,到第 5 次后暂停,等用户操作(如点击重连按钮)再试
- 重连前先检查网络:
wx.getNetworkType返回none就别连,避免无意义重试 - 每次重连前调用
wx.closeSocket()(带状态判断),防止旧连接残留干扰新连接 - 记录重连次数和时间戳,避免 1 分钟内连续触发 20 次重连请求
最易被忽略的一点:小程序从后台切回前台时,onShow 里不能直接重连——此时网络可能尚未恢复,socketTask 也已被系统回收,必须先判断当前是否有有效连接,没有再走完整初始化流程,而不是无脑 connectSocket。











