JavaScript onmessage Event (Server-Sent Events): SSE Message Received

JavaScript onmessage Event: Handling Server-Sent Event Messages

The onmessage event in JavaScript is a crucial part of handling Server-Sent Events (SSE). SSE is a web technology that enables a server to push updates to a client over a single HTTP connection, facilitating real-time data streaming. The onmessage event is triggered whenever the client receives a new message from the server. This article will explore the onmessage event, its syntax, usage, and practical applications, providing you with a comprehensive understanding of how to use SSE effectively.

What is Server-Sent Events (SSE)?

Server-Sent Events (SSE) provide a simple, efficient way to establish a one-way communication channel between a server and a client. Unlike WebSockets, which support bidirectional communication, SSE is designed for situations where the server needs to push updates to the client without the client needing to request them constantly. This makes it ideal for use cases such as live news feeds, stock tickers, and social media updates.

The Role of the onmessage Event

The onmessage event is an event listener that is attached to an EventSource object. An EventSource object is a client-side interface that establishes a connection with an SSE endpoint on the server. When the server sends a message, the onmessage event is triggered, and the associated event handler function is executed.

Understanding the onmessage Event

Syntax

The syntax for using the onmessage event is as follows:

eventSource.onmessage = function(event) {
  // Event handler code here
};

or, using an arrow function:

eventSource.onmessage = (event) => {
  // Event handler code here
};

Where:

  • eventSource: An instance of the EventSource object, representing the connection to the SSE endpoint.
  • onmessage: The event handler property.
  • event: An event object that contains the message data received from the server.

The Event Object

The event object passed to the onmessage event handler has the following key properties:

Property Type Description
`data` String The message payload sent by the server. This can be text, JSON, or other types of data encoded as a string.
`origin` String The origin of the event source, providing security context information.
`lastEventId` String The ID of the last event received from the server. Useful for tracking event sequences and handling reconnects.
`type` String The event type, which is always “message” for the `onmessage` handler.

Note: The data property is the most important, as it contains the actual message sent by the server. 📝

Simple Example

Let’s start with a simple example that demonstrates how to receive and display messages from an SSE server.

<div id="sseOutput1"></div>

<script>
  const sseOutputDiv1 = document.getElementById('sseOutput1');
  if (typeof EventSource !== 'undefined') {
    const sseSource1 = new EventSource('sse_server.php');

    sseSource1.onmessage = (event) => {
      sseOutputDiv1.innerHTML += '<p>Message Received: ' + event.data + '</p>';
    };

    sseSource1.onerror = (error) => {
      console.error('SSE Error:', error);
      sseOutputDiv1.innerHTML += '<p>SSE Error Occured.</p>'
      sseSource1.close();
    }
  } else {
    sseOutputDiv1.innerHTML = "<p>Server-Sent Events are not supported in this browser.</p>";
  }
</script>

In this example, an EventSource is created connecting to sse_server.php. Whenever a message is received, it’s appended to the sseOutputDiv1 element. Also, an error handler is present to report and close the connection in case of error.

Note: The sse_server.php is a placeholder and needs to be a server-side script that sends SSE messages. Example server-side code will be provided later. 💡

Displaying Data Using HTML

Let’s enhance the previous example by dynamically displaying received data in a more structured way, such as updating a list of items.

<ul id="sseList2"></ul>

<script>
  const sseList2 = document.getElementById('sseList2');

    if (typeof EventSource !== 'undefined') {
    const sseSource2 = new EventSource('sse_server.php');

    sseSource2.onmessage = (event) => {
        const listItem = document.createElement('li');
        listItem.textContent = 'Received: ' + event.data;
        sseList2.appendChild(listItem);
    };

    sseSource2.onerror = (error) => {
        console.error('SSE Error:', error);
        sseList2.innerHTML += '<li>SSE Error Occured.</li>'
        sseSource2.close();
    }
    } else {
    sseList2.innerHTML = "<li>Server-Sent Events are not supported in this browser.</li>";
  }
</script>

Here, each received message is displayed as a new list item within the unordered list (sseList2).

Handling JSON Data

Often, servers send data in JSON format, which must be parsed on the client-side.

<div id="sseJsonOutput3"></div>

<script>
  const sseJsonOutput3 = document.getElementById('sseJsonOutput3');

    if (typeof EventSource !== 'undefined') {
    const sseSource3 = new EventSource('sse_server.php');

    sseSource3.onmessage = (event) => {
        try {
            const jsonData = JSON.parse(event.data);
            sseJsonOutput3.innerHTML += '<p>Name: ' + jsonData.name + ', Value: ' + jsonData.value + '</p>';
        } catch (e) {
            sseJsonOutput3.innerHTML += '<p>Invalid JSON data: ' + event.data + '</p>';
        }

    };

    sseSource3.onerror = (error) => {
      console.error('SSE Error:', error);
      sseJsonOutput3.innerHTML += '<p>SSE Error Occured.</p>'
      sseSource3.close();
    }
  } else {
    sseJsonOutput3.innerHTML = "<p>Server-Sent Events are not supported in this browser.</p>";
  }
</script>

In this example, we parse the received data as JSON, handling potential errors, and then display specific fields from the JSON object.

Example: Dynamic Graph Updates Using Canvas

Let’s use the Canvas API to draw a simple graph using data received over SSE. This will demonstrate a more advanced use case of onmessage.

<canvas id="sseCanvas4" width="400" height="200" style="border:1px solid #ddd;"></canvas>

<script>
    const sseCanvas4 = document.getElementById('sseCanvas4');
    const ctx_sse4 = sseCanvas4.getContext('2d');

    let graphData4 = [];

    if (typeof EventSource !== 'undefined') {
    const sseSource4 = new EventSource('sse_server.php');

        sseSource4.onmessage = (event) => {
            try {
                const newData = JSON.parse(event.data);
                if(newData && newData.value){
                    graphData4.push(newData.value);
                }
                if (graphData4.length > 20) {
                    graphData4.shift();
                }
                drawGraph();
             } catch (e) {
                console.error('Error parsing JSON:', event.data, e)
             }
        };

        sseSource4.onerror = (error) => {
          console.error('SSE Error:', error);
          ctx_sse4.fillStyle = "black";
          ctx_sse4.font = "20px Arial";
          ctx_sse4.fillText("SSE Error Occured.", 50, 100)
          sseSource4.close();
        }
    } else {
        ctx_sse4.fillStyle = "black";
        ctx_sse4.font = "20px Arial";
        ctx_sse4.fillText("Server-Sent Events are not supported in this browser.", 50, 100)
    }

    function drawGraph() {
        ctx_sse4.clearRect(0, 0, sseCanvas4.width, sseCanvas4.height);
        ctx_sse4.beginPath();
        ctx_sse4.moveTo(0, sseCanvas4.height);

        const maxValue = Math.max(...graphData4);
        const scaleFactor = sseCanvas4.height / (maxValue > 0 ? maxValue : 1);

        graphData4.forEach((value, index) => {
            const x = (index / (graphData4.length - 1)) * sseCanvas4.width;
            const y = sseCanvas4.height - (value * scaleFactor);
            ctx_sse4.lineTo(x, y);
        });

        ctx_sse4.lineTo(sseCanvas4.width, sseCanvas4.height);
        ctx_sse4.fillStyle = 'rgba(0, 123, 255, 0.2)';
        ctx_sse4.fill();
        ctx_sse4.strokeStyle = '#007bff';
        ctx_sse4.stroke();
    }
</script>

This example displays a line graph that dynamically updates as new data points are received via SSE. This combines both the onmessage event with the Canvas API.

Note: The real-time dynamic behavior of this graph depends on a server that pushes data over SSE.

Server-Side Example (PHP)

Here is a basic PHP script (sse_server.php) that can be used as a server-side endpoint for the above examples. This script sends an SSE message every second with a timestamp or JSON data.

<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');

$counter = 0;
while (true) {
    $time = date('r');
    $data =  array("name" => "Item $counter","value" => rand(10,100));
    $data_json = json_encode($data);
    echo "data: $data_json\n\n";
    ob_flush();
    flush();
    sleep(1);
    $counter++;
}
?>

This PHP script sends a JSON object every second. You need to have this script running on your server to fully test the above examples.

Practical Applications

The onmessage event and SSE are ideal for:

  • Real-time Dashboards: Displaying live metrics, data, and updates.
  • Live Notifications: Pushing notifications to users in real-time.
  • Stock Tickers: Updating financial data without page refreshes.
  • Chat Applications: Receiving new messages from the server in real-time (although WebSockets might be a better choice for bidirectional chat).
  • Progress Updates: Providing feedback on long-running server processes.
  • Live Gaming: Pushing game state updates to clients.

Browser Support

Server-Sent Events and the onmessage event are supported in all modern browsers, making them a reliable choice for real-time web applications. 🌍

Conclusion

The onmessage event is essential for implementing Server-Sent Events in JavaScript. This guide has covered the syntax, usage, and practical examples of the onmessage event, enabling you to build real-time applications effectively. With a solid understanding of SSE and the onmessage event, you can create engaging and dynamic web experiences.