“websocket.send is not a function”表示调用send()的变量不是websocket实例,常见于变量被覆盖、this丢失或误用封装库(如socket.io);需用console.log(obj.constructor.name)验证类型。

WebSocket.send is not a function 是什么情况
这个错误不是网络问题,而是代码层面的引用失效。它意味着你调用 send() 的那个变量,根本就不是 WebSocket 实例。
常见诱因有三个:
- 变量被意外覆盖,比如
let ws = new WebSocket(url); ws = 'xxx';,之后再调ws.send()就会报错 - 在类或闭包里用了
this,但回调中this指向丢失(尤其在事件监听、定时器、箭头函数混用时) - 误把封装库对象当原生 WebSocket 用,比如 Socket.IO 的
socket实例没有send()方法,得用emit()
检查方式很简单:在调用前加一行 console.log(ws.constructor.name),输出不是 WebSocket 就说明对象不对。
readyState !== WebSocket.OPEN 就调 send() 会怎样
WebSocket 连接是异步建立的,new WebSocket() 立刻返回实例,但此时 readyState 很可能是 0(CONNECTING),还没准备好收发数据。
直接发消息不会抛异常,但会被静默丢弃——你完全感知不到失败,消息石沉大海。
正确做法只有两种:
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
- 监听
open事件,在回调里发消息(推荐,逻辑清晰) - 手动判断状态:
if (ws.readyState === WebSocket.OPEN) { ws.send(...) },但要注意:这个判断必须在open之后做,否则容易漏掉时机
别写成 if (ws.readyState !== WebSocket.CONNECTING) ——因为 CLOSING 或 CLOSED 状态下也满足这个条件,照样会崩。
后端发的数据让前端 WebSocket 报 reserved bits 错误
前端控制台出现类似 One or more reserved bits are on: reserved1 = 1, reserved2 = 0, reserved3 = 1 的错误,基本可以锁定是后端没走 WebSocket 协议栈发的数据。
典型场景:
- .NET 项目用了 TouchSocket,但服务端调了
Send()(这是裸 TCP 发送),而不是SendWithWS() - Java Spring WebSocket 中误用
session.getBasicRemote().sendText()向已关闭的 session 发送,或并发写入未加锁 - 自研服务端直接 write raw bytes 到 socket,没按 WebSocket 帧格式(mask、opcode、length、payload)组装
这类错误前端无法修复,必须后端确认发送路径是否经过 WebSocket 编码层。抓包看帧结构是最准的验证方式:合法 WebSocket 帧开头字节必须符合 RFC6455 规范,不能是任意二进制流。
send() 调用成功但对方收不到?先盯住这三点
消息“发出去了”不等于“对方收到了”。常见断点位置:
- 服务端收到但没转发:检查广播逻辑是否过滤了目标 client,或
session.isOpen()判断遗漏 - 客户端 onmessage 没绑定:注意事件监听必须在
open之后注册,否则早期消息会丢失 - 跨域或反向代理拦截:Nginx 需显式透传
Upgrade和Connection头,否则握手成功但后续帧被静默丢弃
最容易被忽略的是:WebSocket 连接在后台标签页或手机息屏后可能被浏览器节流甚至断开,此时 send() 仍返回成功(因为连接对象还活着),但数据实际发不出去。得结合 onclose 和心跳响应来判断真实连通性。










