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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Real-TimeWebSocket
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

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.