0Pricing
Vue Academy · 课时

支持重新连接的 useWebSocket 组合式函数

在组合式函数中封装 WebSocket、使用指数退避自动重连,以及跟踪连接状态

支持重新连接的 useWebSocket 组合式函数 是 CoddyKit 上的免费 Vue Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Vue Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Vue Academy 课程共包含 4 节课。

在可组合函数中封装 WebSockets

将原始 WebSocket 处理逻辑分散在各个组件中会变得杂乱。useWebSocket 可组合函数会集中管理连接状态、重新连接和消息处理,您可以在各处复用它。

我们将逐步构建它。

使用 Ref 跟踪状态

将连接状态公开为响应式的 status ref,这样界面就能显示“正在连接”“已打开”或“已关闭”徽章。

import { ref } from "vue"

export function useWebSocket(url) {
  const status = ref("CLOSED") // CONNECTING | OPEN | CLOSED
  // ...
  return { status }
}

connect 函数

将打开套接字的逻辑封装在内部的 connect 函数中,这样稍后可以再次调用它来重新连接。在每个生命周期事件发生时更新 status。

let ws
function connect() {
  status.value = "CONNECTING"
  ws = new WebSocket(url)
  ws.onopen = () => { status.value = "OPEN" }
  ws.onclose = () => { status.value = "CLOSED"; scheduleReconnect() }
}

逐渐增加延迟的重新连接

在紧密循环中立即重新连接会不断冲击服务器。请使用指数退避:每次尝试失败后等待更长时间,并设置一个上限。

let attempts = 0
function scheduleReconnect() {
  attempts++
  const delay = Math.min(1000 * 2 ** attempts, 30000)
  setTimeout(connect, delay)
}

成功后重置退避延迟

连接成功后,重置尝试次数计数器,这样下次断开连接时,退避就会从头开始,而不是从很长的延迟开始。

ws.onopen = () => {
  status.value = "OPEN"
  attempts = 0
  flushQueue()
}

断开连接时的消息队列

如果用户在套接字断开时发送消息,您不应丢失该消息。请将发出的消息缓存在队列中,并在连接打开后将它们全部处理。

const queue = []
function send(data) {
  const payload = JSON.stringify(data)
  if (ws && ws.readyState === WebSocket.OPEN) {
    ws.send(payload)
  } else {
    queue.push(payload)
  }
}

清空队列

套接字打开后,处理积累的所有消息。从队列前端逐项移除,这样可以保留顺序。

function flushQueue() {
  while (queue.length && ws.readyState === WebSocket.OPEN) {
    ws.send(queue.shift())
  }
}

类型化消息处理器

允许使用者为每种消息 type 注册处理器。将回调函数存储在映射中,并在每个收到的帧到达时根据消息类型进行分发。

const handlers = {}
function on(type, cb) { handlers[type] = cb }

// inside connect:
ws.onmessage = (e) => {
  const msg = JSON.parse(e.data)
  if (handlers[msg.type]) handlers[msg.type](msg.payload)
}

在 onUnmounted 中清理

可组合函数拥有计时器和套接字。使用它的组件卸载时,请将它们清理掉,以免视图消失后重新连接仍不断触发。

import { onUnmounted } from "vue"

let reconnectTimer
onUnmounted(() => {
  clearTimeout(reconnectTimer)
  if (ws) ws.close(1000, "component unmounted")
})

避免在有意关闭后重新连接

由您自己的清理逻辑执行的正常关闭(代码 1000)不应触发重新连接。请跟踪 intentional 标志,并在该标志已设置时跳过调度。

let intentional = false
function close() { intentional = true; ws.close(1000) }

ws.onclose = () => {
  status.value = "CLOSED"
  if (!intentional) scheduleReconnect()
}

完整的可组合函数结构

现在所有部分组合起来了:创建时连接,公开 status、send 和 on,断开时将消息加入队列,使用退避策略重新连接,并自动完成清理。

export function useWebSocket(url) {
  const status = ref("CLOSED")
  // connect, scheduleReconnect, send, on, flushQueue, cleanup...
  connect()
  return { status, send, on, close }
}

// usage:
// const { status, send, on } = useWebSocket("wss://...")

快速检查

检查您对重新连接策略的理解。

回顾

您构建了一个健壮的 useWebSocket 可组合函数:

  • status ref 会反映 CONNECTING / OPEN / CLOSED 状态,供界面使用。
  • 使用有上限的指数退避进行重新连接,并在成功后重置计数器。
  • 断开连接时将发出的消息加入队列,并在连接打开后清空队列。
  • 将收到的帧分发给按类型设置的处理器回调函数。
  • 在 onUnmounted 中清理计时器和套接字,在有意关闭后跳过重新连接。

常见问题解答

「支持重新连接的 useWebSocket 组合式函数」课时是免费的吗?

是的 — 「支持重新连接的 useWebSocket 组合式函数」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Vue Academy 课程的其余内容,请升级到 CoddyKit PRO。 Vue Academy 课程共包含 4 节课。

「支持重新连接的 useWebSocket 组合式函数」这节课中我会学到什么?

在组合式函数中封装 WebSocket、使用指数退避自动重连,以及跟踪连接状态 你通过在浏览器中直接运行的动手代码来练习 Vue Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Vue Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Vue Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。

「支持重新连接的 useWebSocket 组合式函数」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Vue Academy 课中编写并运行代码吗?

能。每节 Vue Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 浏览器中的 WebSocket 基础
  2. 在 Vue 中使用 Socket.io 客户端
  3. 构建实时聊天组件
  4. 支持重新连接的 useWebSocket 组合式函数
← 返回 Vue Academy