Skip to content

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,避免本地缓冲无限增长。

基于 MIT 许可发布