支持重新连接的 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 可组合函数:
statusref 会反映 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 反馈 — 无需本地设置。
此课程中的所有课时
- 浏览器中的 WebSocket 基础
- 在 Vue 中使用 Socket.io 客户端
- 构建实时聊天组件
- 支持重新连接的 useWebSocket 组合式函数