@iam4x/reconnecting-websocket
v1.4.0
Published
A robust, TypeScript-first WebSocket client with automatic reconnection, exponential backoff, and comprehensive event handling.
Readme
@iam4x/reconnecting-websocket
A robust, TypeScript-first WebSocket client with automatic reconnection, exponential backoff, and comprehensive event handling.
Features
- ✅ Automatic Reconnection - Automatically reconnects on connection loss with exponential backoff
- ✅ Message Queueing - Messages sent while disconnected are queued and delivered on reconnection
- ✅ Connection Timeout - Configurable timeout to detect stalled connections
- ✅ Inactivity Detection - Optionally reconnect when no messages are received within a timeout
- ✅ Event-Driven API - Familiar event listener pattern matching WebSocket API
- ✅ TypeScript Support - Full TypeScript definitions included
- ✅ Customizable - Configurable retry delays, backoff factors, and WebSocket implementations
- ✅ Reconnect Events - Separate
reconnectevent for tracking reconnection attempts - ✅ Memory Safe - Proper cleanup of timers and event listeners
Installation
bun add @iam4x/reconnecting-websocketor
npm install @iam4x/reconnecting-websocketQuick Start
import { ReconnectingWebSocket } from "@iam4x/reconnecting-websocket";
const ws = new ReconnectingWebSocket("wss://echo.websocket.org");
ws.addEventListener("open", () => {
console.log("Connected!");
ws.send("Hello, Server!");
});
ws.addEventListener("message", (event: MessageEvent) => {
console.log("Received:", event.data);
});
ws.addEventListener("close", (event) => {
console.log("Connection closed:", event.code, event.reason);
});
ws.addEventListener("reconnect", () => {
console.log("Reconnected successfully!");
});
ws.addEventListener("error", (event: Event) => {
console.error("WebSocket error:", event);
});API Reference
Constructor
new ReconnectingWebSocket(url: string, options?: ReconnectOptions)Creates a new ReconnectingWebSocket instance and immediately attempts to connect.
Parameters
url(string): The WebSocket server URL (e.g.,"wss://example.com")options(ReconnectOptions, optional): Configuration options (see below)
Options
interface ReconnectOptions {
retryDelay?: number; // Initial retry delay in ms (default: 1000)
maxRetryDelay?: number; // Maximum retry delay in ms (default: 30000)
connectionTimeout?: number; // Connection timeout in ms (default: 10000)
backoffFactor?: number; // Exponential backoff multiplier (default: 2)
healthCheckInterval?: number; // Health check interval in ms (default: 30000)
watchingInactivityTimeout?: number; // Inactivity timeout in ms (default: 0, disabled)
WebSocketConstructor?: typeof WebSocket; // Custom WebSocket implementation
}Option Details
- retryDelay: The initial delay before the first reconnection attempt (in milliseconds)
- maxRetryDelay: The maximum delay between reconnection attempts. The delay will grow exponentially but won't exceed this value
- connectionTimeout: If a connection doesn't establish within this time, it will be aborted and retried
- backoffFactor: The multiplier for exponential backoff. Each retry delay is multiplied by this factor
- healthCheckInterval: Interval for checking if the socket is still healthy. Set to
0to disable (default: 30000ms) - watchingInactivityTimeout: If no message is received within this timeout, the connection will be closed and a reconnection attempt will be made. Useful for detecting silent connection failures or keeping connections alive on servers that expect regular activity. Set to
0to disable (default: 0, disabled). A common value is300000(5 minutes) - WebSocketConstructor: Allows you to provide a custom WebSocket implementation (useful for Node.js environments using libraries like
ws)
Methods
addEventListener(event, listener)
Adds an event listener to the socket.
ws.addEventListener("open", (event: Event) => {
// Handle open event
});Events:
"open"- Emitted when connection is established"message"- Emitted when a message is received (payload:MessageEvent)"close"- Emitted when connection closes (payload:{ code: number, reason: string })"reconnect"- Emitted when successfully reconnected after a disconnection"error"- Emitted when an error occurs (payload:Event)
removeEventListener(event, listener)
Removes an event listener from the socket.
const handler = (event: Event) => console.log("Connected");
ws.addEventListener("open", handler);
ws.removeEventListener("open", handler);send(data)
Sends data through the WebSocket connection. If the socket is not open, messages are automatically queued and sent once the connection is established.
ws.send("Hello, Server!");
ws.send(JSON.stringify({ type: "ping" }));Note: Messages sent while disconnected are queued and delivered in order when the socket opens. The queue is cleared if close() is called.
close(code?, reason?)
Closes the WebSocket connection and prevents automatic reconnection.
ws.close(); // Close with default code
ws.close(1000, "Normal closure"); // Close with code and reasonAfter calling close(), the socket will not automatically reconnect. Create a new instance to reconnect.
Properties
readyState
Returns the current ready state of the WebSocket connection.
if (ws.readyState === WebSocket.OPEN) {
ws.send("Data");
}Values:
WebSocket.CONNECTING(0) - Connection is being establishedWebSocket.OPEN(1) - Connection is open and readyWebSocket.CLOSED(3) - Connection is closed
bufferedAmount
Returns the number of bytes of data that have been queued using send() but not yet transmitted.
if (ws.bufferedAmount === 0) {
ws.send("Large message");
}Note: Returns 0 if the socket is not connected.
Examples
Custom Retry Configuration
const ws = new ReconnectingWebSocket("wss://api.example.com", {
retryDelay: 500, // Start with 500ms delay
maxRetryDelay: 60000, // Cap at 60 seconds
backoffFactor: 1.5, // Gentle backoff
connectionTimeout: 5000 // 5 second timeout
});Inactivity Timeout
Use watchingInactivityTimeout to automatically reconnect when no messages are received for a period of time. This is useful for detecting silent connection failures or when the server expects regular activity:
const ws = new ReconnectingWebSocket("wss://api.example.com", {
watchingInactivityTimeout: 300000, // Reconnect if no message received for 5 minutes
});
ws.addEventListener("message", (event: MessageEvent) => {
// Each message received resets the inactivity timer
console.log("Received:", event.data);
});
ws.addEventListener("close", (event) => {
// This will fire when inactivity timeout triggers a reconnect
console.log("Connection closed:", event.code, event.reason);
});Using with Node.js
import WebSocket from "ws";
import { ReconnectingWebSocket } from "@iam4x/reconnecting-websocket";
const ws = new ReconnectingWebSocket("wss://api.example.com", {
WebSocketConstructor: WebSocket as any,
});Handling Reconnections
Messages sent while disconnected are automatically queued and delivered when the connection is restored:
const ws = new ReconnectingWebSocket("wss://api.example.com");
ws.addEventListener("reconnect", () => {
console.log("Reconnected! Resuming operations...");
});
// Safe to call anytime - messages are queued if disconnected
ws.send("message1");
ws.send("message2");
// When socket opens/reconnects, queued messages are sent automaticallyNote: Calling close() clears the message queue. Messages queued before a forced close are discarded.
Error Handling
ws.addEventListener("error", (event: Event) => {
console.error("WebSocket error occurred:", event);
// Error events typically precede close events
// The socket will automatically attempt to reconnect
});
ws.addEventListener("close", (event) => {
if (event.code !== 1000) {
console.warn("Connection closed unexpectedly:", event.code, event.reason);
}
});Manual Connection Management
const ws = new ReconnectingWebSocket("wss://api.example.com");
// Later, close the connection
ws.close();
// To reconnect, create a new instance
const ws2 = new ReconnectingWebSocket("wss://api.example.com");Reconnection Behavior
The library uses exponential backoff for reconnection attempts:
- First retry: After
retryDelaymilliseconds - Second retry: After
retryDelay * backoffFactormilliseconds - Third retry: After
retryDelay * backoffFactor²milliseconds - And so on... up to
maxRetryDelay
Example with defaults (retryDelay: 1000, backoffFactor: 2, maxRetryDelay: 30000):
- Attempt 1: Wait 1 second
- Attempt 2: Wait 2 seconds
- Attempt 3: Wait 4 seconds
- Attempt 4: Wait 8 seconds
- Attempt 5: Wait 16 seconds
- Attempt 6+: Wait 30 seconds (max)
TypeScript Support
Full TypeScript definitions are included. The library is written in TypeScript and exports all necessary types.
import type { ReconnectingWebSocket } from "@iam4x/reconnecting-websocket";License
MIT
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
