myHotTake

Tag: JavaScript connections

  • How to Track Online Users with WebSockets in JavaScript

    If you find this story helpful, feel free to like or share it!


    I’m the host of a radio station, and I want to keep track of all my listeners to know who’s tuned in and who’s not. Each listener has a special radio that can send signals back to me. This radio connection is like a WebSocket, a two-way communication line between my station and the listener.

    One day, as I start my broadcast, I imagine each listener turning on their radio and sending me a signal: “Hey, I’m online!” Each signal they send is a little ping, telling me they’re listening in. As the host, I jot down a list of everyone who’s tuned in, just like a server keeping track of connected users.

    As the show goes on, I occasionally send out little messages to my listeners, like song titles or trivia questions. Their radios are always ready to receive, just like a WebSocket connection always being open for data exchanges.

    Now, sometimes a listener decides to switch off their radio or maybe their battery runs out. When that happens, their radio sends me a final signal: “Goodbye, I’m going offline.” I scratch their name off my list. This is akin to a WebSocket connection closing when a user goes offline, and the server updating its records.

    But sometimes, I don’t hear a goodbye signal. Maybe their radio just went silent due to bad reception. To make sure I know who’s really there, every so often, I send out a heartbeat signal: “Are you still with me?” Those radios that can still hear me will reply, “Yes, I’m here!” If I don’t get a response, I know they’re no longer tuned in, and I update my list accordingly.

    In this way, my radio station, with its trusty radios, helps me keep track of who’s listening and who’s not, much like how presence tracking works with WebSockets to monitor online and offline users. Each connection is alive, constantly communicating, ensuring I always know who’s part of my audience.


    First, I set up my radio station (server) using Node.js with the ws library, which lets me handle WebSocket connections. Here’s a basic example:

    const WebSocket = require('ws');
    const wss = new WebSocket.Server({ port: 8080 });
    
    const listeners = new Set();
    
    wss.on('connection', (ws) => {
      // A new radio turns on
      listeners.add(ws);
      console.log('A new listener has tuned in.');
    
      // Handle messages from the listener
      ws.on('message', (message) => {
        console.log(`Received message: ${message}`);
      });
    
      // Handle the listener going offline
      ws.on('close', () => {
        listeners.delete(ws);
        console.log('A listener has tuned out.');
      });
    
      // Heartbeats to check if listeners are still online
      const heartbeat = setInterval(() => {
        if (ws.readyState === WebSocket.OPEN) {
          ws.send('Are you still there?');
        }
      }, 30000);
    
      ws.on('pong', () => {
        console.log('Listener is still online.');
      });
    
      ws.on('close', () => {
        clearInterval(heartbeat);
      });
    });

    In this code, each time a listener connects, I add them to my list of listeners. When they send a message, I log it, simulating the interaction of answering trivia or song titles.

    When a listener goes offline (closes the connection), I remove them from the list, just like crossing their name off my radio station’s roster.

    To ensure my listener list is accurate, I periodically send a heartbeat message asking, “Are you still there?” If a listener is still connected, they respond, and I know they’re still tuned in. This is akin to checking if their radio signal is still strong.

    On the client side, here’s a simple JavaScript example of how a listener might interact with the station:

    const ws = new WebSocket('ws://localhost:8080');
    
    ws.onopen = () => {
      console.log('Connected to the radio station.');
      ws.send('Hello from the listener!');
    };
    
    ws.onmessage = (event) => {
      console.log(`Station says: ${event.data}`);
      // Respond to heartbeats
      if (event.data === 'Are you still there?') {
        ws.send('Yes, I am here!');
      }
    };
    
    ws.onclose = () => {
      console.log('Disconnected from the radio station.');
    };

    This client code connects to my radio station, sends a greeting, and listens for messages. When a heartbeat is received, it responds to let me know they’re still tuned in.

    Key Takeaways:

    1. WebSockets enable real-time, two-way communication between the server and clients, much like a radio station and its listeners.
    2. JavaScript provides the tools to set up WebSocket servers and clients, allowing you to track online/offline status effectively.
    3. Heartbeats are a crucial technique to ensure the server’s presence list is accurate, checking if connections are still active.
  • How Do WebSockets Handle Connection Events in JavaScript?

    If you find this story helpful, feel free to like or share it with others who might enjoy it!


    I’m a lighthouse keeper, and my job is to guide ships safely to shore. Each ship is like a WebSocket connection, and the way I handle these ships is similar to managing connection lifecycle events in WebSockets.

    When a new ship appears on the horizon, I light the beacon and wave signals, ensuring it knows I’m ready to guide it. This is like the open event in WebSockets, where I establish a connection and get ready to communicate. The ship and I exchange signals to confirm our connection is strong and reliable.

    As the ship approaches, we communicate regularly, exchanging vital information. This is akin to the messages being sent and received over the WebSocket connection. I make sure everything is running smoothly, much like handling data transmissions.

    However, occasionally, storms roll in. If a ship encounters trouble and sends distress signals, I act quickly to provide assistance, just as I would handle an error event in a WebSocket connection. I assess the situation, try to understand the problem, and take appropriate measures to ensure we can continue communicating effectively.

    Finally, once the ship safely docks at the harbor, it signals its departure. I acknowledge its arrival and prepare for its farewell, similar to the close event in WebSockets. I ensure the connection is properly closed, and I’m ready to guide the next ship that comes my way.

    As a lighthouse keeper, managing these ships—like handling WebSocket connection lifecycle events—is all about being prepared, responsive, and ensuring smooth communication from start to finish.


    Part 2: JavaScript Code Examples

    In the world of JavaScript, managing WebSocket connections is akin to my duties as a lighthouse keeper. Here’s how I translate those actions into code:

    1. Opening the Connection (Lighting the Beacon): When a new ship appears—when I open a WebSocket connection—I set up the initial communication channel:
       const socket = new WebSocket('ws://example.com/socket');
    
       socket.addEventListener('open', (event) => {
           console.log('Connection opened:', event);
           // Ready to send and receive messages
       });

    Here, the open event listener is like lighting my beacon, signaling readiness to communicate.

    1. Handling Messages (Exchanging Signals): As the ship approaches and we exchange signals, I handle incoming messages:
       socket.addEventListener('message', (event) => {
           console.log('Message from server:', event.data);
           // Process the incoming data
       });

    The message event listener ensures I process signals—data—from the server.

    1. Handling Errors (Dealing with Storms): When a storm hits, I handle errors to maintain communication:
       socket.addEventListener('error', (event) => {
           console.error('WebSocket error observed:', event);
           // Handle the error and attempt recovery if necessary
       });

    The error event listener acts like my response to a distress signal, ensuring I address issues that arise.

    1. Closing the Connection (Docking the Ship): Finally, when the ship docks, I close the connection properly:
       socket.addEventListener('close', (event) => {
           console.log('Connection closed:', event);
           // Clean-up and prepare for future connections
       });

    The close event listener signifies the end of our communication, just as I acknowledge the ship’s safe arrival.

    Key Takeaways:

    • Lifecycle Events: Just like managing ships, handling open, message, error, and close events ensures smooth WebSocket communication.
    • Preparedness: Being ready to respond to each event is crucial, similar to how a lighthouse keeper must be vigilant.
    • Error Handling: Addressing errors promptly ensures that the connection remains stable and can recover from issues.
    • Clean Closure: Closing connections properly prevents resource leaks and prepares the system for future interactions.