Encapsulating WebSocket with Reconnection, Heartbeat, and Event Handling in JavaScript/TypeScript
This article explains how to wrap WebSocket in a reusable JavaScript/TypeScript class that provides automatic reconnection, heartbeat monitoring, event callbacks, connection state management, and graceful destruction, while also comparing WebSocket advantages over traditional HTTP polling for real‑time H5 applications.
The article introduces the need for a WebSocket wrapper in an H5 project where the app runs inside a WebView, describing problems such as lost connections when the mobile device screen is off and the limitations of polling‑based solutions.
WebSocket Basics
WebSocket is a full‑duplex protocol defined by RFC 6455 that enables a persistent TCP connection, allowing both client and server to push data without the request‑response overhead of HTTP. Its key characteristics include bidirectional communication, low latency, a single persistent connection, lightweight headers, and resource efficiency.
Why Not HTTP?
Traditional HTTP follows a request‑response model, requiring frequent polling or long‑polling for real‑time updates, which leads to high resource consumption, increased network traffic, and latency. Even with HTTP/1.1 Keep‑Alive, the model still incurs handshake overhead for each request.
WebSocket Wrapper Features
Automatic reconnection with configurable max attempts and interval.
Heartbeat mechanism to keep the connection alive.
Event callbacks for message, open, and close events.
Connection state management (open, closed, destroyed).
Graceful destruction of the instance.
JavaScript Implementation
class ReSocket {
constructor(url, options = {}) {
this.url = url;
this.options = options;
this.socket = null;
this.maxReconnectTimes = options.maxReconnectTimes || 5;
this.reconnectTimes = 0;
this.reconnectInterval = options.reconnectInterval || 3000;
this.isClosed = false;
this.isOpen = false;
this.isConnect = false;
this.isReconnecting = false;
this.isDestroyed = false;
this.reconnectTimer = null;
this.heartbeatTimer = null;
this.heartbeatInterval = options.heartbeatInterval || 30000;
this.heartbeatData = options.heartbeatData || "ping";
this.onMessageCallback = null;
this.onOpenCallback = null;
this.onCloseCallback = null;
}
// ... (methods createSocket, connect, reconnect, send, onMessage, onOpen, onClose, startHeartbeat, stopHeartbeat, close, destroy)
}
export { ReSocket };TypeScript Implementation
type ReSocketOptions = {
maxReconnectTimes?: number;
reconnectInterval?: number;
heartbeatInterval?: number;
heartbeatData?: string;
};
class ReSocket {
private url: string;
private socket: WebSocket | null = null;
private maxReconnectTimes: number;
private reconnectTimes: number = 0;
private reconnectInterval: number;
private isClosed: boolean = false;
private isOpen: boolean = false;
private isConnect: boolean = false;
private isReconnecting: boolean = false;
private isDestroyed: boolean = false;
private reconnectTimer: NodeJS.Timeout | null = null;
private heartbeatTimer: NodeJS.Timeout | null = null;
private heartbeatInterval: number;
private heartbeatData: string;
private onMessageCallback: ((message: string) => void) | null = null;
private onOpenCallback: (() => void) | null = null;
private onCloseCallback: (() => void) | null = null;
constructor(url: string, options: ReSocketOptions = {}) {
this.url = url;
this.maxReconnectTimes = options.maxReconnectTimes || 5;
this.reconnectInterval = options.reconnectInterval || 3000;
this.heartbeatInterval = options.heartbeatInterval || 30000;
this.heartbeatData = options.heartbeatData || "ping";
}
// ... (methods similar to the JavaScript version, with type annotations)
}
export { ReSocket };Usage Example
First, set up a simple Node WebSocket server using the ws library, then create an index.html page that imports the compiled socket.js and instantiates new ReSocket('ws://localhost:8080') . Call connect() , register onMessage callbacks, and observe logs in the browser console.
Handling Edge Cases
The wrapper also addresses common pain points such as browser compatibility, proxy restrictions, network state detection, heartbeat timeout, large‑payload handling, and page visibility changes. Example code shows how to listen for the visibilitychange event to pause or resume the connection when the page is hidden or shown, and a periodic check to detect inactive pages and attempt reconnection.
Conclusion
The author reflects on the effort spent writing the tutorial, shares personal career updates, and encourages readers to follow the public account for more technical content.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.