主题
WebSocket 客户端(浏览器)
建立连接与收发消息
js
const ws = new WebSocket('wss://example.com/ws', ['json'])
ws.addEventListener('open', () => {
ws.send(JSON.stringify({ type: 'subscribe', topic: 'orders' }))
})
ws.addEventListener('message', (event) => {
const message = JSON.parse(event.data)
console.log(message)
})
ws.addEventListener('close', ({ code, reason, wasClean }) => {
console.log({ code, reason, wasClean })
})
ws.addEventListener('error', () => {
// error 通常没有可用的错误详情;以 close 事件处理重连。
console.error('WebSocket 发生错误')
})构造函数的第二个参数是可选子协议列表;服务端会从中选择一个,并在 ws.protocol 中返回。它用于约定消息协议,不是认证机制。
状态与二进制数据
readyState 依次为 CONNECTING(0)、OPEN(1)、CLOSING(2)、CLOSED(3)。仅在 OPEN 时发送消息。
js
if (ws.readyState === WebSocket.OPEN) {
ws.send('hello')
}
ws.binaryType = 'arraybuffer'
ws.addEventListener('message', (event) => {
if (event.data instanceof ArrayBuffer) {
console.log(new Uint8Array(event.data))
}
})可控重连
不要对正常关闭(如用户退出)重连;异常关闭时使用指数退避,并加入随机抖动。
js
let socket
let stopped = false
let attempts = 0
function connect() {
socket = new WebSocket('wss://example.com/ws')
socket.addEventListener('open', () => {
attempts = 0
})
socket.addEventListener('close', () => {
if (stopped) return
const base = Math.min(1_000 * 2 ** attempts, 30_000)
const delay = base * (0.5 + Math.random())
attempts += 1
setTimeout(connect, delay)
})
}
function disconnect() {
stopped = true
socket?.close(1000, 'user disconnect')
}重连后应重新认证、重新订阅,并按业务序号补齐遗漏数据。发送频率较高时检查 socket.bufferedAmount,避免本地缓冲无限增长。
