binarytype 必须在 open 之后、接收前设置为 "arraybuffer";接收图片帧时需将 arraybuffer 转 blob(动态识别格式)再生成 object url 渲染到 canvas,并及时 revoke 以防内存泄漏。

binaryType 必须在 open 之后、接收前设置
WebSocket 的 binaryType 不是连接时的构造参数,也不能在 onopen 回调外随意设置。如果写在 new WebSocket() 之后立即赋值,但此时连接尚未建立,部分浏览器(如 Chrome)会静默忽略,导致后续 event.data 仍是 Blob 而非预期的 ArrayBuffer。
正确时机是监听 open 事件后、开始接收数据前:
ws.onopen = () => { ws.binaryType = "arraybuffer"; };- 不要写成
ws.binaryType = "arraybuffer"; ws = new WebSocket(...); - 也不要依赖
ws.readyState === 1在任意位置动态设置——必须确保连接已就绪且尚未收到第一条消息
接收图片帧时用 ArrayBuffer + Blob URL 渲染到 canvas
服务端按帧推送 JPEG 二进制(如每 33ms 一帧),前端不能直接把 ArrayBuffer 当作图片源;需走 Blob → object URL → Image 流程,否则 ctx.drawImage() 会报错或空白。
关键步骤和易错点:
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
- 收到
event.data后先确认它是instanceof ArrayBuffer,不是Blob或string - 创建
Blob时必须指定{ type: "image/jpeg" },否则Image加载可能失败或解码异常 - 每次绘制前要调用
URL.revokeObjectURL(prevUrl),否则内存持续增长,几秒后页面卡顿 - 示例片段:
let currentImageUrl = null;<br>ws.onmessage = (e) => {<br> if (!(e.data instanceof ArrayBuffer)) return;<br> if (currentImageUrl) URL.revokeObjectURL(currentImageUrl);<br> const blob = new Blob([e.data], { type: "image/jpeg" });<br> currentImageUrl = URL.createObjectURL(blob);<br> const img = new Image();<br> img.onload = () => { ctx.drawImage(img, 0, 0); };<br> img.src = currentImageUrl;<br>};
为什么不用 Blob 模式接收图片?
设 binaryType = "blob" 看似更“自然”,但实际带来两个硬伤:
-
Blob.arrayBuffer()是异步操作,需await blob.arrayBuffer(),在高频帧场景(如 30fps)下会造成明显延迟和帧丢弃 - 无法直接用
Blob构造Image(img.src = blob不合法),仍得转成 object URL,多一层封装无收益 -
ArrayBuffer可直接参与 TypedArray 操作(如做灰度转换、ROI 提取),Blob则必须先读取再解析,丧失实时处理能力
服务端推送格式不一致时怎么兼容?
真实环境中,服务端可能混发 JPEG 帧、PNG 帧,甚至带简单头部(如 4 字节长度 + 图像数据)。这时不能硬编码 type: "image/jpeg"。
稳妥做法是提取魔数判断类型:
- 取
new Uint8Array(e.data, 0, 4)查看前 4 字节 -
[0xff, 0xd8]→ JPEG;[0x89, 0x50, 0x4e, 0x47]→ PNG;[0x47, 0x49, 0x46]→ GIF - 根据识别结果动态传入
Blob的type参数,避免Image加载失败 - 若服务端加了自定义头部(如 8 字节 header + image body),需用
new Uint8Array(e.data).slice(8)截取有效图像数据再构造Blob
头部解析和类型识别这两步一旦漏掉,img.onload 就永远不会触发,但控制台也不报错——这是最常被忽略的静默失败点。










