Learn WebSocket - Native WebSocket API: Client Side (Browser)
Episode 4 of 34

Learn WebSocket - Native WebSocket API: Client Side (Browser)

This episode dissects the browser's built-in WebSocket API: creating an instance, the four event handlers, the send and close methods, and the readyState and bufferedAmount properties, plus a simple reconnection pattern.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

All the protocol concepts we dissected in episodes 2 and 3 now take practical form: the browser's built-in WebSocket API. You do not need to install any library — every modern browser already implements RFC 6455.

Episode 4 takes you through this API from scratch: creating a WebSocket instance, registering the four event handlers, using the send and close methods, reading the readyState and bufferedAmount properties, and putting together reconnection logic. By the end of the episode you will have a complete WebSocket client ready to talk to any server.

Creating a WebSocket Instance

URL and Subprotocols

Opening a connection is just one line:

JSCreating a WebSocket instance
const ws = new WebSocket("wss://example.com/ws");
 
const wsChat = new WebSocket("wss://example.com/chat", ["chat-v1", "chat-v2"]);

The second parameter is a list of requested subprotocols. new WebSocket(url, protocols) creates the instance and immediately starts the handshake. The server may pick one from that list via the Sec-WebSocket-Protocol header.

Properties Visible Right Away

Immediately after the instance is created:

  • ws.readyState holds the connection state (0 to 3).
  • ws.bufferedAmount holds the number of bytes not yet sent.
  • ws.url shows the final URL after redirects.

The Four Event Handlers

onopen

Called when the handshake completes and the connection is ready to use:

JSThe onopen handler
ws.onopen = () => {
  console.log("koneksi terbuka");
  ws.send("halo server");
};

Make sure all initial messages are sent from inside onopen — sending before this event can fail because the connection is not yet OPEN.

onmessage

Called every time a data frame arrives. This is the heart of a real-time application:

JSThe onmessage handler
ws.onmessage = (event) => {
  const data = event.data;
  if (typeof data === "string") {
    renderText(data);
  } else {
    renderBinary(data);
  }
};

event.data can be a string for text frames, or a Blob and ArrayBuffer for binary frames. The default binary behavior is Blob; it can be changed with ws.binaryType = "arraybuffer".

onerror and onclose

Errors and closures need to be handled separately:

JSThe onerror and onclose handlers
ws.onerror = (event) => {
  console.error("terjadi error", event);
};
 
ws.onclose = (event) => {
  console.log("koneksi ditutup", event.code, event.reason);
};

onclose receives an object with event.code and event.reason. Note: onerror is not always followed by a closure, but onclose almost always comes after a fatal error.

Important Methods and Properties

send() and close()

The two main methods:

JSsend and close
ws.send("pesan teks");
ws.send(new Blob([data]));
ws.send(new Uint8Array([1, 2, 3]));
 
ws.close(1000, "tutup normal");

ws.send() accepts a string, Blob, or ArrayBufferView. ws.close(code, reason) starts a polite closure: a close frame is sent, then the state moves to CLOSED.

readyState and bufferedAmount

Both properties are important for debugging:

JSReading bufferedAmount
function kirimPelan(ws, teks) {
  ws.send(teks);
  if (ws.bufferedAmount > 0) {
    console.log("masih ada data tertunda:", ws.bufferedAmount);
  }
}

ws.bufferedAmount tells you how many bytes have not yet reached the network — an early signal of backpressure that we will discuss in a later episode.

Simple Reconnection Logic

Reconnecting After a Disconnect

A WebSocket connection can drop at any time. This is the minimum pattern you must have:

JSSimple reconnection
let ws;
 
function hubungkan() {
  ws = new WebSocket("wss://example.com/ws");
 
  ws.onclose = () => {
    setTimeout(hubungkan, 3000);
  };
}
 
hubungkan();

Calling hubungkan() from inside onclose with setTimeout(hubungkan, 3000) is the essence of reconnection. A later episode will upgrade this pattern with exponential backoff and retry limits.

Feature Detection and Fallback

All modern browsers support WebSocket, but defensive code is still worthwhile:

JSDetecting WebSocket support
if (window.WebSocket) {
  // jalan normal
} else {
  // fallback ke polling atau SSE
}

Check window.WebSocket before using the API. For older browsers, the common fallback is SSE or long polling — exactly the options from episode 1.

Warning

On mobile, WebSocket connections die more often due to network switching. Always install reconnection logic and state recovery code like the upcoming episode covers, not just an onopen handler.

Closing

Episode 4 equipped you with a native WebSocket client: creating an instance, the four event handlers, the send and close methods, the readyState and bufferedAmount properties, and a simple reconnection pattern to withstand dropped connections.

Key takeaways:

  • The WebSocket API exists in the browser with no library installation needed.
  • Four event handlers: onopen, onmessage, onerror, and onclose.
  • send accepts a string, Blob, or typed array; binaryType controls the binary format.
  • close uses a code and reason for a clean closure.
  • readyState and bufferedAmount are the main debugging tools.
  • Reconnection should be in place from the start, not after production misbehaves.

In the next episode we move to the server side: a WebSocket server with Node.js and the ws library — installation, server creation, the connection event, broadcast, and managing connected clients. You will have a complete client and server pair.