Skip to main content
Home

Built and signed on GitHub Actions

Works with
This package works with Cloudflare Workers, Node.js, Deno, Bun, Browsers
This package works with Cloudflare Workers
This package works with Node.js
This package works with Deno
This package works with Bun
This package works with Browsers
JSR Score100%
Downloads7/wk
Published3 weeks ago (1.2.3)

WebSocket with auto-reconnection — a drop-in replacement for the standard WebSocket.

@nktkas/rews

npm JSR bundlejs

WebSocket with auto-reconnection — a drop-in replacement for the standard WebSocket.

Installation

Node.js (choose your package manager)

npm i @nktkas/rews

pnpm add @nktkas/rews

yarn add @nktkas/rews

Deno

deno add jsr:@nktkas/rews

Usage

Simply replace WebSocket with ReconnectingWebSocket:

import { ReconnectingWebSocket } from "@nktkas/rews";

// const ws = new WebSocket("wss://...");
const ws = new ReconnectingWebSocket("wss://...", {
  // optional reconnection options
});
ws.addEventListener("message", (e) => console.log(e.data));
ws.send("data");

Options

interface ReconnectingWebSocketOptions {
  /**
   * Custom WebSocket constructor.
   * @default globalThis.WebSocket
   */
  WebSocket?: new (url: string | URL, protocols?: string | string[]) => WebSocket;
  /**
   * Maximum number of reconnection attempts.
   * @default 3
   */
  maxRetries?: number;
  /**
   * Maximum time in ms to wait for a connection to open.
   * Set to `null` to disable.
   * @default 10_000
   */
  connectionTimeout?: number | null;
  /**
   * Delay before reconnection in ms.
   * May be a number or a function that returns a number.
   * @param attempt - The current attempt number.
   * @default (attempt) => Math.min(~~(1 << attempt) * 150, 10_000); // Exponential backoff (max 10s)
   */
  reconnectionDelay?: number | ((attempt: number) => number);
}

Differences from standard WebSocket

Automatic Reconnection

ReconnectingWebSocket will automatically attempt to reconnect when the connection is lost, up to a configurable number of retries.

Message Buffering

Messages sent while the connection is closed are buffered and sent once the connection is re-established.

Preserved Event Listeners

All event listeners added to the ReconnectingWebSocket instance are preserved across reconnections.

Dynamic URL and Protocol Providers

The url and protocols parameters accept functions that return their respective values. These functions are invoked on each reconnection attempt, enabling dynamic endpoint resolution or authentication token refresh.

const ws = new ReconnectingWebSocket(
  () => `wss://example.com?token=${getAuthToken()}`,
  () => ["protocol-v1"],
);

Terminate Event

The terminate event fires when the WebSocket permanently closes.

Error Codes:

  • RECONNECTION_LIMIT - Maximum reconnection attempts reached
  • TERMINATED_BY_USER - Closed via close() method
  • UNKNOWN_ERROR - An unknown error occurred during reconnection

Usage:

ws.addEventListener("terminate", (event) => {
  const error = event.detail; // ReconnectingWebSocketError
  console.log(error.code); // Error code
  console.log(error.cause); // Original error if available
});

// Check termination status manually
if (ws.isTerminated) {
  const error = ws.terminationReason!; // ReconnectingWebSocketError
  console.log(error.code); // Error code
  console.log(error.cause); // Original error if available
}

Why Use This

Before:

// Requires manual reconnection logic, listener re-attachment, and message buffering
let ws: WebSocket;
let attempts = 0;
const messageHandler = (e) => console.log(e.data);
const messageQueue: string[] = [];

function connect() {
  ws = new WebSocket("wss://example.com");

  // Re-attach listener on each reconnection
  ws.addEventListener("message", messageHandler);

  ws.onopen = () => {
    attempts = 0;

    // Send queued messages
    while (messageQueue.length > 0) {
      ws.send(messageQueue.shift()!);
    }
  };

  ws.onclose = () => {
    // Attempt reconnection
    if (attempts++ < 3) {
      setTimeout(connect, 1000);
    }
  };

  ws.onerror = () => {
    ws.close();
  };
}

function send(data: string) {
  if (ws.readyState === WebSocket.OPEN) {
    ws.send(data);
  } else {
    messageQueue.push(data); // Buffer message if not connected
  }
}

connect();
send("data");

After:

// Original WebSocket API remains unchanged despite reconnection logic
const ws = new ReconnectingWebSocket("wss://example.com");
ws.addEventListener("message", (e) => console.log(e.data)); // listener persists across reconnections
ws.send("data"); // buffered if disconnected
Built and signed on
GitHub Actions

Report package

Please provide a reason for reporting this package. We will review your report and take appropriate action.

Please review the JSR usage policy before submitting a report.

Add Package

deno add jsr:@nktkas/rews

Import symbol

import * as rews from "@nktkas/rews";
or

Import directly with a jsr specifier

import * as rews from "jsr:@nktkas/rews";

Add Package

pnpm i jsr:@nktkas/rews
or (using pnpm 10.8 or older)
pnpm dlx jsr add @nktkas/rews

Import symbol

import * as rews from "@nktkas/rews";

Add Package

yarn add jsr:@nktkas/rews
or (using Yarn 4.8 or older)
yarn dlx jsr add @nktkas/rews

Import symbol

import * as rews from "@nktkas/rews";

Add Package

vlt install jsr:@nktkas/rews

Import symbol

import * as rews from "@nktkas/rews";

Add Package

npx jsr add @nktkas/rews

Import symbol

import * as rews from "@nktkas/rews";

Add Package

bunx jsr add @nktkas/rews

Import symbol

import * as rews from "@nktkas/rews";