Node.js
WebSocket
Einaros WS
Socket Programming
JavaScript

Node JS - How Can You Tell If A Socket Is Already Open With The Einaros WS Socket Module?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

With the ws module in Node.js, the standard way to check whether a socket is open is to inspect readyState and compare it against WebSocket.OPEN. That answer is technically simple, but reliable code also needs to think about state transitions, reconnection, and the fact that a socket can close immediately after you check it.

Core Sections

Read the readyState correctly

A ws socket has four main states:

  • 'WebSocket.CONNECTING'
  • 'WebSocket.OPEN'
  • 'WebSocket.CLOSING'
  • 'WebSocket.CLOSED'

The normal open check is:

javascript
1const WebSocket = require("ws");
2
3if (socket.readyState === WebSocket.OPEN) {
4  socket.send("hello");
5}

Use the named constants instead of numeric values. It keeps the code readable and avoids magic numbers such as 1 for open.

The best time to send is usually the open event

In client code, the safest time to send an initial message is from the open handler rather than from arbitrary code that happens to run after construction.

javascript
1const WebSocket = require("ws");
2
3const ws = new WebSocket("ws://localhost:8080");
4
5ws.on("open", () => {
6  console.log("socket open");
7  ws.send("initial payload");
8});
9
10ws.on("message", (data) => {
11  console.log(data.toString());
12});

If your code naturally sends only from open and later from known-active handlers, you need fewer scattered readiness checks.

Wrap sending in a helper

In larger codebases, a small helper is useful so the open-state rule is consistent everywhere.

javascript
1const WebSocket = require("ws");
2
3function safeSend(ws, payload) {
4  if (ws.readyState === WebSocket.OPEN) {
5    ws.send(payload);
6    return true;
7  }
8  return false;
9}

This lets callers decide what to do if the socket is not ready.

javascript
if (!safeSend(ws, JSON.stringify({ type: "ping" }))) {
  console.log("socket not open, skipping send");
}

That centralization is helpful when you later add metrics, logging, or retry behavior.

State checks are snapshots, not guarantees

A readyState check only tells you the socket’s state at that moment. A connection can close a millisecond later. So even correct state checking does not remove the need for close and error handling.

That means robust code should always listen for:

  • 'close'
  • 'error'
  • sometimes ping and pong handling for long-lived links

For example:

javascript
1ws.on("close", () => {
2  console.log("socket closed");
3});
4
5ws.on("error", (err) => {
6  console.error("socket error", err.message);
7});

The important mindset is that readiness is dynamic, not permanent.

Server broadcasts must check each client

On the server side, broadcasting requires the same check for every connected client.

javascript
1const WebSocket = require("ws");
2const { WebSocketServer } = WebSocket;
3
4const wss = new WebSocketServer({ port: 8080 });
5
6function broadcast(message) {
7  for (const client of wss.clients) {
8    if (client.readyState === WebSocket.OPEN) {
9      client.send(message);
10    }
11  }
12}
13
14wss.on("connection", (client) => {
15  client.on("message", (message) => {
16    broadcast(`echo: ${message}`);
17  });
18});

Skipping the state check can cause sends to fail when one client has already started closing.

Queue or retry when connection timing matters

If your app may try to send before the connection opens, queueing is often better than silently dropping messages.

javascript
1const pending = [];
2
3function enqueueOrSend(ws, payload) {
4  if (ws.readyState === WebSocket.OPEN) {
5    ws.send(payload);
6  } else {
7    pending.push(payload);
8  }
9}
10
11ws.on("open", () => {
12  while (pending.length > 0) {
13    ws.send(pending.shift());
14  }
15});

This is useful during startup bursts, reconnect flows, or applications where early messages are meaningful and should not be lost.

Common Pitfalls

  • Comparing readyState to raw numbers instead of WebSocket.OPEN makes the code harder to read and maintain.
  • Assuming one open-state check guarantees the socket will stay open for the entire send path ignores how quickly state can change.
  • Sending outside the open event without a readiness strategy often causes dropped messages or exceptions.
  • Broadcasting to all clients without checking each client’s state fails when some connections are closing or already closed.
  • Treating reconnect behavior as separate from state checking leads to fragile long-lived real-time code.

Summary

  • In ws, a socket is open when readyState === WebSocket.OPEN.
  • The open event is the best place for initial sends.
  • A helper such as safeSend keeps readiness logic consistent.
  • 'readyState is only a snapshot, so close and error handling still matter.'
  • On servers, check every client before broadcasting and consider queueing or reconnect logic for resilient systems.

Course illustration
Course illustration

All Rights Reserved.