WebSocket不直接支持JavaScript对象,需手动序列化/反序列化;推荐JSON+自定义处理器处理常见复杂类型,或用MessagePack/Protobuf提升性能;应封装统一消息通道并做好错误防护。

WebSocket 本身只传输字符串或 ArrayBuffer,不直接支持 JavaScript 对象。要处理复杂对象(如含函数、Date、RegExp、Map、Set、undefined、循环引用等),必须在发送前手动序列化、接收后手动反序列化——关键在于选择合适策略,而非依赖 WebSocket 自身能力。
用 JSON + 自定义处理器应对常见复杂类型
JSON 是最轻量、兼容性最好的基础方案,但原生不支持 Date、RegExp、undefined、NaN、Infinity、函数、循环引用等。可通过 JSON.stringify() 的 replacer 和 JSON.parse() 的 reviver 参数扩展:
-
Date:序列化时转为 ISO 字符串,反序列化时识别
__type: "Date"字段重建 -
RegExp:存为
{ __type: "RegExp", source: "...", flags: "gim" },反序列化时 new RegExp -
undefined / NaN / Infinity:用特殊占位符(如
"__UNDEFINED__")代替,reviver 中还原 -
循环引用:需预处理(如用
cycle.js或自实现引用标记),但会增加体积和复杂度;生产环境建议避免发送含循环引用的对象
用 MessagePack 或 Protocol Buffers 提升性能与类型保真度
当需要更高效率、更小体积或强类型保障时,可替换 JSON:
-
MessagePack(推荐前端用
@msgpack/msgpack):二进制格式,天然支持Uint8Array、Map、Set、BigInt(需配置),体积比 JSON 小 30–50%,解析更快;需前后端约定 schema,但无需 IDL -
Protocol Buffers(需
protobufjs):严格 schema 驱动,适合微服务间通信;前端需提前加载 .proto 描述并生成代码,灵活性较低但类型最安全 - 注意:二者均不直接支持函数、DOM 节点、window 等运行时对象——这类对象本就不该通过 WebSocket 传输
封装统一的 WS 消息通道,自动处理编解码
避免每次 send/recv 都写重复逻辑,建议封装一个带序列化策略的 WebSocket 类:
- 发送时:
send(data)内部调用serialize(data)(如 JSON.stringify + replacer 或 msgpack.encode) - 接收时:监听
message事件,对event.data自动调用deserialize(data),再触发自定义onmessage回调 - 可注入不同序列化器(如
new WSSocket(url, { codec: 'msgpack' })),便于后期切换 - 示例片段:
import { encode, decode } from '@msgpack/msgpack';
// 发送:socket.send(encode({ type: 'user:update', payload: user }))
// 接收:const obj = decode(event.data);
特别注意边界情况与错误防护
真实场景中,序列化/反序列化失败会导致静默断连或数据错乱:
- 始终 try/catch
JSON.parse()和decode(),失败时记录日志并触发onerror,不要让异常冒泡到未捕获错误监听器 - 服务端返回非预期格式(如 HTML 错误页、空响应)时,
event.data可能是字符串但无法解析——需先判断typeof event.data === 'string'或instanceof ArrayBuffer - 对敏感字段(如 token、用户隐私数据)不在序列化层加密,应在传输层(WSS)或业务层加解密,避免混淆职责
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











