← Back to all snippets
JAVASCRIPT

Real-time API Communication with WebSockets

Establish persistent, full-duplex communication channels with a backend API using WebSockets for instant, event-driven data exchange in web applications.

/**
 * Sets up a WebSocket connection for real-time API communication.
 * @param {string} wsUrl - The WebSocket endpoint URL (e.g., 'ws://localhost:8080/ws' or 'wss://example.com/ws').
 * @param {object} handlers - An object containing event handler functions.
 *   @param {function(): void} [handlers.onOpen] - Called when the WebSocket connection opens.
 *   @param {function(event: MessageEvent): void} [handlers.onMessage] - Called when a message is received.
 *   @param {function(event: CloseEvent): void} [handlers.onClose] - Called when the WebSocket connection closes.
 *   @param {function(event: Event): void} [handlers.onError] - Called when a WebSocket error occurs.
 * @returns {{ send: (message: string | object) => void, close: () => void, getConnection: () => WebSocket }} An object with methods to interact with the WebSocket.
 */
function setupWebSocket(wsUrl, handlers = {}) {
    let ws;
    let reconnectAttempts = 0;
    const MAX_RECONNECT_ATTEMPTS = 5;
    const RECONNECT_DELAY = 2000; // milliseconds

    const connect = () => {
        ws = new WebSocket(wsUrl);

        ws.onopen = (event) => {
            console.log('WebSocket connection opened:', event);
            reconnectAttempts = 0; // Reset attempts on successful connection
            if (handlers.onOpen) handlers.onOpen();
        };

        ws.onmessage = (event) => {
            console.log('WebSocket message received:', event.data);
            if (handlers.onMessage) handlers.onMessage(event);
        };

        ws.onclose = (event) => {
            console.warn('WebSocket connection closed:', event);
            if (handlers.onClose) handlers.onClose(event);

            // Attempt to reconnect if the closure was not intentional
            if (!event.wasClean && reconnectAttempts < MAX_RECONNECT_ATTEMPTS) {
                reconnectAttempts++;
                console.log(`Attempting to reconnect WebSocket (attempt ${reconnectAttempts}/${MAX_RECONNECT_ATTEMPTS})...`);
                setTimeout(connect, RECONNECT_DELAY * Math.pow(2, reconnectAttempts - 1)); // Exponential backoff for reconnect
            }
        };

        ws.onerror = (event) => {
            console.error('WebSocket error:', event);
            if (handlers.onError) handlers.onError(event);
            // Error might lead to close, which then triggers reconnect logic
        };
    };

    const send = (message) => {
        if (ws && ws.readyState === WebSocket.OPEN) {
            const dataToSend = typeof message === 'object' ? JSON.stringify(message) : message;
            ws.send(dataToSend);
        } else {
            console.warn('WebSocket is not open. Message not sent:', message);
        }
    };

    const close = () => {
        if (ws) {
            ws.close(1000, 'Client initiated close'); // 1000 is Normal Closure
        }
    };

    // Initial connection
    connect();

    return {
        send,
        close,
        getConnection: () => ws // For direct access if needed, though discouraged
    };
}

// Example usage:
// const myWebSocket = setupWebSocket('wss://echo.websocket.events', {
//     onOpen: () => {
//         console.log('Connected to WebSocket server!');
//         myWebSocket.send('Hello from client!');
//         myWebSocket.send({ type: 'SUBSCRIBE', channel: 'updates' });
//     },
//     onMessage: (event) => {
//         try {
//             const data = JSON.parse(event.data);
//             console.log('Parsed message:', data);
//             // Update UI based on data
//             document.getElementById('websocket-messages').innerHTML += `<p>${JSON.stringify(data)}</p>`;
//         } catch (e) {
//             console.log('Raw message:', event.data);
//             document.getElementById('websocket-messages').innerHTML += `<p>${event.data}</p>`;
//         }
//     },
//     onClose: (event) => {
//         console.log('WebSocket disconnected:', event.reason);
//     },
//     onError: (event) => {
//         console.error('WebSocket encountered an error:', event);
//     }
// });

// // Send messages manually
// // setTimeout(() => myWebSocket.send('Another message after 5 seconds.'), 5000);

// // Close the connection after a while
// // setTimeout(() => myWebSocket.close(), 15000);
How it works: This snippet demonstrates how to establish and manage a WebSocket connection for real-time, bidirectional communication with an API. The `setupWebSocket` function handles connection creation, defines event listeners for `open`, `message`, `close`, and `error` events, and includes basic reconnection logic with exponential backoff for resilience. WebSockets offer a more efficient alternative to traditional HTTP polling for applications requiring instant data updates, such as chat applications, live dashboards, or gaming.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs