0Pricing
Vue Academy · Lesson

useWebSocket Composable with Reconnection

Wrapping WebSocket in a composable, auto-reconnect with exponential backoff, status tracking.

useWebSocket Composable with Reconnection is a free Vue Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Vue Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Wrapping WebSockets in a Composable

Raw WebSocket handling scattered across components gets messy. A useWebSocket composable centralizes connection state, reconnection, and message handling — and you reuse it everywhere.

We will build it piece by piece.

Tracking Status with a Ref

Expose the connection state as a reactive status ref so the UI can show "Connecting", "Open", or "Closed" badges.

import { ref } from "vue"

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

The connect Function

Encapsulate opening the socket in an inner connect function so we can call it again later to reconnect. Update status on each lifecycle event.

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

Reconnection with Increasing Delay

Reconnecting instantly in a tight loop hammers the server. Use exponential backoff: wait longer after each failed attempt, up to a cap.

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

Resetting Backoff on Success

Once a connection succeeds, reset the attempt counter so the next disconnect starts the backoff from the beginning rather than from a long delay.

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

A Message Queue While Disconnected

If the user sends while the socket is down, you should not lose the message. Buffer outgoing messages in a queue and flush them once the connection opens.

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

Flushing the Queue

When the socket opens, drain everything that piled up. Shift items off the front so order is preserved.

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

Typed Message Handlers

Let consumers register handlers per message type. Store callbacks in a map and dispatch by the message type on each incoming frame.

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)
}

Cleanup in onUnmounted

The composable owns timers and a socket. Tear them down when the using component unmounts so reconnection does not keep firing after the view is gone.

import { onUnmounted } from "vue"

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

Avoiding Reconnect After Intentional Close

A clean close (code 1000) from your own teardown should NOT trigger a reconnect. Track an intentional flag and skip scheduling when it is set.

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

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

The Full Composable Shape

Everything comes together: connect on creation, expose status, send, and on, queue while down, reconnect with backoff, and clean up automatically.

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://...")

Quick Check

Check your understanding of the reconnection strategy.

Recap

You built a robust useWebSocket composable:

  • A status ref reflects CONNECTING / OPEN / CLOSED for the UI.
  • Reconnect with exponential backoff, capped, and reset the counter on success.
  • Queue outgoing messages while disconnected and flush on open.
  • Dispatch incoming frames to per-type handler callbacks.
  • Clean up timers and the socket in onUnmounted, skipping reconnect after an intentional close.

Frequently asked questions

Is the “useWebSocket Composable with Reconnection” lesson free?

Yes — the full text of “useWebSocket Composable with Reconnection” is free to read here on the web, and the Vue Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Vue Academy course, upgrade to CoddyKit PRO.

What will I learn in “useWebSocket Composable with Reconnection”?

Wrapping WebSocket in a composable, auto-reconnect with exponential backoff, status tracking. You practise Vue Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Vue Academy?

No prior experience is required. Vue Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “useWebSocket Composable with Reconnection” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Vue Academy lesson?

Yes. Every Vue Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. WebSocket Basics in the Browser
  2. Socket.io Client with Vue
  3. Building a Real-Time Chat Component
  4. useWebSocket Composable with Reconnection
← Back to Vue Academy