Vue Academy · Lesson

useWebSocket Composable with Reconnection

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

Lesson 4 of 413 steps

useWebSocket Composable with Reconnection is a free Vue Academy lesson on CoddyKit. This is lesson 4 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the Vue Academy learning path, and your progress syncs across the web and the CoddyKit app. The Vue Academy course includes 4 lessons in total.

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.
Free to start

Learn HTML with an AI tutor — free

Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.

Courses
42
Lessons
156

Frequently Asked Questions

Is the “useWebSocket Composable with Reconnection” lesson free?

Yes — any 3 lessons of the Vue Academy learning path, including “useWebSocket Composable with Reconnection”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The Vue Academy course includes 4 lessons in total.

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, so you can start here or from the beginning and move at your own pace. This is lesson 4 of 4.

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