Frontend Development 8 min read

Building a WebSocket Manager for Real‑Time Message Push in JavaScript

This article demonstrates how to create a reusable WebSocket manager in JavaScript that handles connection creation, automatic heartbeat, message sending, reconnection attempts, and graceful closure, providing a complete front‑end solution for real‑time communication without relying on polling.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Building a WebSocket Manager for Real‑Time Message Push in JavaScript

Requirement Analysis

The module should be encapsulated in a class and provide the following capabilities:

Create and close a WebSocket object.

Enable a heartbeat mechanism to keep the connection alive.

Push incoming messages to business‑logic callbacks.

Implement a reconnection strategy with a maximum number of attempts.

Implementation

Create WebSocket Class

File WebSocketManager.js defines the WebSocketManager class and initializes essential properties.

export default class WebSocketManager {
    constructor(url = null, userId = null, receiveMessageCallback = null) {
        this.socket = null; // WebSocket object
        this.pingTimeout = null; // heartbeat timer
        this.reconnectTimeout = 5000; // reconnection interval (ms)
        this.maxReconnectAttempts = 10; // max reconnection attempts
        this.reconnectAttempts = 0; // current attempt count
        this.id = userId; // user identifier
        this.url = url; // WebSocket server URL
        this.receiveMessageCallback = receiveMessageCallback; // callback for received messages
    }
}

Initialize WebSocket Object

The start method checks that both URL and user ID are provided before establishing the connection.

export default class WebSocketManager {
    constructor() {
        // ... omitted
    }
    /**
     * Initialize
     */
    async start() {
        if (this.url && this.id) {
            // connect WebSocket
            this.connectWebSocket();
        } else {
            console.error('WebSocketManager errors: please provide connection URL and user ID');
        }
    }
}

Create WebSocket Connection

The connectWebSocket method builds a unique identifier from the user ID and a random value, creates the WebSocket instance, and registers event listeners for open, message, close, and error events.

export default class WebSocketManager {
    constructor() {
        // ... omitted
    }
    /**
     * Create WebSocket connection
     */
    connectWebSocket() {
        // generate unique ID (server‑side requirement)
        let id = `${this.id}-${Math.random()}`;
        // create WebSocket object
        this.socket = new WebSocket(this.url, id);

        // handle open event – start heartbeat
        this.socket.addEventListener('open', event => {
            this.startHeartbeat();
        });

        // handle incoming messages
        this.socket.addEventListener('message', event => {
            this.receiveMessage(event);
        });

        // handle close event – attempt reconnection
        this.socket.addEventListener('close', event => {
            clearTimeout(this.pingTimeout);
            clearTimeout(this.reconnectTimeout);
            if (this.reconnectAttempts < this.maxReconnectAttempts) {
                this.reconnectAttempts++;
                this.reconnectTimeout = setTimeout(() => {
                    this.connectWebSocket();
                }, this.reconnectTimeout);
            } else {
                // reset attempts after reaching the limit
                this.reconnectAttempts = 0;
                console.error('WebSocketManager errors: Max reconnect attempts reached. Unable to reconnect.');
            }
        });

        // handle error event
        this.socket.addEventListener('error', event => {
            console.error('WebSocketManager error:', event);
        });
    }
}

Heartbeat Mechanism

A periodic ping message is sent every 10 seconds to keep the connection alive.

export default class WebSocketManager {
    constructor() {
        // ... omitted
    }
    /**
     * Start heartbeat
     */
    startHeartbeat() {
        this.pingTimeout = setInterval(() => {
            // send heartbeat message
            this.sendMessage('ping');
        }, 10000); // every 10 seconds
    }
    /**
     * Send a message
     * @param {String} message Message content
     */
    sendMessage(message) {
        if (this.socket.readyState === WebSocket.OPEN) {
            this.socket.send(message);
        } else {
            console.error('WebSocketManager error: WebSocket connection is not open. Unable to send message.');
        }
    }
}

Receive Message

The receiveMessage method logs the incoming data and forwards it to the user‑provided callback.

export default class WebSocketManager {
    constructor() {
        // ... omitted
    }
    /**
     * Handle received message
     */
    receiveMessage(event) {
        // custom business logic here
        console.log('receiveMessage:', event.data);
        this.receiveMessageCallback && receiveMessageCallback(event.data);
    }
}

Close Connection

The closeWebSocket method terminates the socket and clears all timers.

export default class WebSocketManager {
    constructor() {
        // ... omitted
    }
    /**
     * Close the connection
     */
    closeWebSocket() {
        this.socket.close();
        // clear timers and reset attempts
        clearTimeout(this.pingTimeout);
        clearTimeout(this.reconnectTimeout);
        this.reconnectAttempts = 0;
    }
}

Usage Example

Import the manager, provide a message‑handling callback, instantiate it with the server URL and user ID, and start the connection.

/**
 * Message callback
 */
const receiveMessage = (res) => {
    console.log('Received message callback:', res);
};

const socketManager = new WebSocketManager('ws://example.com/socket', 'userid292992', receiveMessage);
socketManager.start();

Conclusion

The code above offers a straightforward WebSocket implementation for front‑end projects. Developers can adapt and extend it according to specific business requirements. For the full source, refer to the linked GitHub repository.

frontendreal-timeJavaScriptWebSocketheartbeatreconnection
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.