feat(web): BaseWebSocket 支持二进制帧收发

onmessage 原来无条件 JSON.parse,收到 Yjs 二进制帧会落进 catch。
加 onBinary 钩子与 sendRaw,让 collab 通道能复用基类的重连与心跳。
This commit is contained in:
2026-08-28 02:06:13 -06:00
parent 59191c9433
commit c04570b4ad

View File

@@ -140,6 +140,7 @@ export class BaseWebSocket<T extends WebSocketMessage = WebSocketMessage> {
// 迟到的 onclose / onerror 不该去改现在这条连接的状态
const ws = new WebSocket(this.url)
this.ws = ws
ws.binaryType = "arraybuffer"
ws.onopen = () => {
if (ws !== this.ws) return
@@ -154,6 +155,14 @@ export class BaseWebSocket<T extends WebSocketMessage = WebSocketMessage> {
ws.onmessage = (event) => {
if (ws !== this.ws) return
// Yjs 这类二进制帧不是 JSON交给子类。基类的 pong / force_logout 都是文本帧,
// 不会走到这条路径上
if (typeof event.data !== "string") {
this.onBinary(event.data as ArrayBuffer)
return
}
try {
const data = JSON.parse(event.data) as T
@@ -330,6 +339,24 @@ export class BaseWebSocket<T extends WebSocketMessage = WebSocketMessage> {
return false
}
/**
* 二进制帧钩子。基类不认二进制默认丢弃collab 这类通道在子类里覆盖。
* 和 onMessage 对称,不要在这里做 JSON 解析。
*/
protected onBinary(_data: ArrayBuffer) {}
/**
* 不做 JSON 序列化的发送。Yjs 的 update / awareness 本身就是 Uint8Array
* 走 send() 会被 JSON.stringify 成一个 {"0":12,"1":3,...} 的对象。
*/
sendRaw(data: ArrayBuffer | Uint8Array) {
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
this.ws.send(data)
return true
}
return false
}
/**
* 添加消息处理器
*/