Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@bdky/websocket-client

Package Overview
Dependencies
Maintainers
3
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@bdky/websocket-client

轻量级 WebSocket 客户端 SDK,基于事件驱动架构,支持自动重连与消息队列管理

latest
npmnpm
Version
1.0.2
Version published
Weekly downloads
10
Maintainers
3
Weekly downloads
 
Created
Source

@bdky/websocket-client

A robust, feature-rich WebSocket client for the browser with built-in heartbeat, automatic reconnection with exponential backoff, message buffering, and ACK/NACK support.

Features

  • Heartbeat (Ping/Pong) — Configurable keep-alive with automatic timeout detection
  • Auto Reconnect — Exponential backoff with jitter, max retries, and instant-reconnect option
  • Message Buffering — Messages sent while disconnected are queued and flushed on reconnect
  • ACK/NACK — Optional application-level delivery confirmation with configurable timeout
  • Connection Timeout — Abort stalled connection attempts
  • Typed Events — Full TypeScript support with strongly-typed event emitter (Emittery)
  • Lightweight — Zero dependencies beyond emittery, tree-shakeable ESM + CJS output

Installation

npm install @bdky/websocket-client
# or
yarn add @bdky/websocket-client

Quick Start

import {WebSocketClient} from '@bdky/websocket-client';

const client = new WebSocketClient({
    url: 'wss://example.com/ws',
});

client.emitter.on('open', () => {
    console.log('Connected');
    client.send('Hello, server!');
});

client.emitter.on('message', ({data}) => {
    console.log('Received:', data);
});

client.emitter.on('close', ({code, reason}) => {
    console.log(`Closed: ${code} ${reason}`);
});

client.connect();

API

new WebSocketClient(options)

Creates a new WebSocket client instance.

Options

OptionTypeDefaultDescription
urlstringrequiredWebSocket server URL
protocolsstring | string[]undefinedSubprotocol(s)
connectionTimeoutnumber10000Connection timeout in ms
backoffPartial<IBackoffOptions>see belowReconnection backoff strategy
heartbeatPartial<IHeartbeatOptions> | nullsee belowHeartbeat config, null to disable
ackPartial<IAckOptions>see belowACK/NACK config
binaryTypeBinaryType'blob'Binary data type

Properties

PropertyTypeDescription
readyStateWebSocketStateCurrent connection state: 'idle' | 'connecting' | 'open' | 'closing' | 'closed' | 'reconnecting'
urlstringThe WebSocket URL
bufferedAmountnumberNumber of messages waiting in the send buffer
emitterEmittery<IWebSocketEvents>Typed event emitter

Methods

MethodDescription
connect()Initiate the WebSocket connection
send(data)Send data. Auto-buffers if not connected
close(code?, reason?)Gracefully close the connection (no reconnect)
dispose()Destroy the instance, release all resources

Events

Subscribe via client.emitter.on(event, handler):

EventPayloadDescription
open{event}Connection established
close{code, reason, wasClean}Connection closed
error{event}WebSocket error occurred
message{data, event}Message received (excludes pong & ack)
reconnecting{attempt, delay}About to reconnect
reconnected{attempt}Successfully reconnected
heartbeat_timeoutundefinedPong not received within timeout
ack{messageId}Server acknowledged a message
nack{messageId}ACK timeout, message not confirmed

Heartbeat

Automatic ping/pong keep-alive to detect dead connections early.

const client = new WebSocketClient({
    url: 'wss://example.com/ws',
    heartbeat: {
        interval: 30_000,     // Send ping every 30s
        timeout: 5_000,       // Wait 5s for pong
        pingMessage: 'ping',  // Ping payload (string or () => string)
        isPong: (data) => data === 'pong',  // Identify pong responses
    },
});

Set heartbeat: null to disable heartbeat entirely.

Default values:

OptionDefault
interval30000
timeout5000
pingMessage'ping'
isPong(data) => data === 'pong'

Auto Reconnect

Exponential backoff reconnection with configurable limits.

const client = new WebSocketClient({
    url: 'wss://example.com/ws',
    backoff: {
        initialDelay: 1_000,      // Start with 1s delay
        maxDelay: 30_000,         // Cap at 30s
        maxRetries: 10,           // Give up after 10 attempts (0 = infinite)
        instantReconnect: false,  // Skip delay on first retry
    },
});

client.emitter.on('reconnecting', ({attempt, delay}) => {
    console.log(`Reconnect #${attempt} in ${delay}ms`);
});

client.emitter.on('reconnected', ({attempt}) => {
    console.log(`Reconnected after ${attempt} attempts`);
});

Default values:

OptionDefault
initialDelay1000
maxDelay30000
maxRetries0 (infinite)
instantReconnectfalse

The delay formula is: min(initialDelay * 2^attempt, maxDelay)

Message Buffering

Messages sent while disconnected are automatically buffered and flushed when the connection is (re)established.

const client = new WebSocketClient({url: 'wss://example.com/ws'});

// These messages are queued, not lost
client.send('message-1');
client.send('message-2');

console.log(client.bufferedAmount); // 2

// On connect, buffered messages are sent automatically
client.connect();

ACK / NACK

Application-level message delivery confirmation.

const client = new WebSocketClient({
    url: 'wss://example.com/ws',
    ack: {
        enabled: true,
        timeout: 5_000,
        getMessageId: (data) => {
            const msg = JSON.parse(data as string);
            return msg.id;
        },
        parseAck: (data) => {
            const msg = JSON.parse(data as string);
            return msg.type === 'ack' ? msg.id : null;
        },
    },
});

client.emitter.on('ack', ({messageId}) => {
    console.log(`Message ${messageId} confirmed`);
});

client.emitter.on('nack', ({messageId}) => {
    console.log(`Message ${messageId} timed out — no ACK received`);
});

JSON Protocol Example

import {WebSocketClient} from '@bdky/websocket-client';

interface ServerMessage {
    type: 'data' | 'pong' | 'ack';
    payload?: unknown;
    id?: string;
}

const client = new WebSocketClient({
    url: 'wss://api.example.com/ws',
    heartbeat: {
        interval: 25_000,
        timeout: 5_000,
        pingMessage: () => JSON.stringify({type: 'ping'}),
        isPong: (data) => {
            if (typeof data !== 'string') {
                return false;
            }
            try {
                const msg: ServerMessage = JSON.parse(data);
                return msg.type === 'pong';
            }
            catch {
                return false;
            }
        },
    },
    backoff: {
        initialDelay: 1_000,
        maxDelay: 30_000,
        maxRetries: 5,
    },
});

client.emitter.on('message', ({data}) => {
    if (typeof data === 'string') {
        const msg: ServerMessage = JSON.parse(data);
        console.log('Server says:', msg);
    }
});

client.emitter.on('error', () => {
    console.error('Connection error');
});

client.connect();

Exports

// Classes
export {WebSocketClient, ExponentialBackoff, ArrayQueue};

// Types
export type {
    IWebSocketClientOptions,
    IBackoffOptions,
    IHeartbeatOptions,
    IAckOptions,
    IWebSocketEvents,
    IResolvedOptions,
    WebSocketState,
    WebSocketEmitter,
    BufferData,
};

// Default constants
export {
    DEFAULT_CONNECTION_TIMEOUT,
    DEFAULT_BACKOFF,
    DEFAULT_HEARTBEAT,
    DEFAULT_ACK,
};

License

MIT

Keywords

websocket

FAQs

Package last updated on 20 Mar 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts