Learn HTML5 - Part 3: Server-sent Events APIs


You might be interested in learning HTML5 from the very first article of this series since this is the third part of my Learn HTML5 series.

Server-Sent Events

Server-Sent Events (SSE) is a recent HTML5 specification in combination with the EventSource API designed for streaming updates. Prior to that you might be familiar with the bidirectional communication channel, known as WebSockets, used very much and tons of server implementations are available on the internet. However, the second server-push technology of HTML5 yet stays in the shadows.
To enable efficient server-to-client streaming of event data it is basically text-based. For example real-time notifications or updates, like Facebook, Twitter, stock exchange updates and so on generated on the server. Basically we have the following two types of components that SSE introduces:
  • EventSource Interface
  • Event Stream
The EventSource interface allows the client to receive push notifications from the server as DOM events and and the "event stream" data format, that is used to deliver the individual updates.
For a long time, we previously considered the HTTP protocol as a request-response model that uses bidirectional communication, in other words when you as a client sends a request to the server and waits for the response then again sends a future request. What clear to you.? Here you see that the server cannot communicate with the client unless it's requested, this process is also called COMET.
COMET flow chart
Comet applications can be broadly classified as
In streaming the web/application server is kept open for a long time.
Long polling
In polling, the server holds the connection until it has data to push then the client must open a new polling request.
Streaming with Hidden iframe
In this, the HTML page contains a hidden iframe and this is sent as a chunked block, that implicitly declares it as infinitely long.
Streaming with XHR
XMLHttpRequest object in JavaScript used by Ajax applications for browser–server communication.
XHR long Polling
The client sends a request through the XMLHttpRequest JavaScript object.
Script tag long-polling
Process is nearly the same as XHR long Polling but the script code is embedded in a <script> tag.
Server-Sent Events are designed to reduce the overheads of the preceding only bidirectional communication way. In HTML5 we have a native way to handle SSE, an API is defined in HTML5 that opens an HTTP connection for receiving push notifications time-by-time from a server.
You can enable event-based streaming over HTTP using SSE. As in the picture above you saw it is a one-way connection so that the server can send updates to the client. You just need to create an EventSource object via JS and the server flushing event data as and when there is an update triggered without terminating the stream.
The following are the main interesting points of EventSource that you need to know:
  • new EventSource(URL): Used to create an EventSource object that starts listening for events.
  • readyState: The readyState tells us whether we are connecting, open, or closed.
  • onopen, onmessage: Initiate when new EventSource object occurs.
  • addEventListener: Used for default message and custom messages with addEventListener.
  • event.data: Used to encode and decode the object using the data property of the event object.
  • close: Closes the connection from the client-side.
SSE flow chart
In the following figure, you will see how SSE works after the client/server is connected.
The very first instance that initiates on the server-side is OutboundEvent. It will initiate when any new event is generated and contains the data that will be passed to the client and here as you might understand when the server sends data to the client it will always be in a serialized format. So, here the OutboundEventWriter comes in the process and serializes the data on the server-side and this time you need to specify the media type of the data in OutboundEvent. There are no restrictions on providing specific media types only.
Now to the client-side, InboundEvent is responsible for handling the incoming data from the server and as for readability InbounEventReader is used to deserialize the data.
Using SSEBroadCaster, we are able to broadcast events to multiple clients that are connected to the server.
Browser support for server-sent events:
The following are key features of Server-Sent Events:
  • Low latency delivery via a single connection
  • Connection are long-lived
  • Cross-browser message parsing
  • No unbounded buffers in message parsing
  • Automatic tracking of last seen message
  • Auto reconnect in case of disconnection
  • Client message notifications as DOM events
Here's an example of how to work with Server-Sent Events, we create a Server-Side Event request for a specific time and raise an event for date and time and this event will fire each second during the Server-Side Event time duration.
Let's assume you are receiving an updated server date and time each second and then next you need to tell the browser that this response is Server-Side Events response and for that add the Server-Side Events receivers in the initialize function.
Now add the code inside our initialize function using JavaScript EventSource class as in the following:
  1. <script>    
  2.    function initialize() {}    
  3. </script> 
Now initialize the EventSource as in the following
  1. if (window.EventSource == #ff0000) {}    
  3. var source = new EventSource('your data source');   
    Now hook up the events with an EventSource
    First create the onopen event handler as in the following:
    1. source.onopen = function (event) {    
    2.    document.getElementById('your target where you want to show the message').innerHTML += 'Connection Opened.';    
    3. };  
    Then create an onerror event handler for handling the connection if there is any error that occurs or it is closed as in the following
    1. source.onerror = function (event) {    
    2.    if (event.eventPhase == EventSource.CLOSED) {    
    3.        document.getElementById('your target where you want to show the message').innerHTML += 'Connection Closed.';    
    4.    }    
    5. };   
      Finally the onmessage event handler is to fire everytime when new data has arrived from our request as in the following
      1. source.onmessage = function (event) {    
      2.    document.getElementById(''your target where you want to show the message ').innerHTML += event.data;    
      3. };   
        Done, as you saw Server-Sent Events will run until the the response is closed by you as I define in my example response will come for only one minute.
        Create a div to display the output as in the following:
        1. <div id="OutputDiv">    
        2. </div> 
        Complete Code
        1. <!DOCTYPE html>    
        2. <html>    
        3. <head runat="server">    
        4.     <title>Server Sent Events</title>    
        5.     <script>    
        6.         function initialize() {    
        7.             if (window.EventSource == undefined) {    
        8.                 document.getElementById('OutputDiv').innerHTML = "Your browser doesn't support Server Side Events.";    
        9.                 return;    
        10.             }    
        11.             var source = new EventSource('GetDateTime.aspx');    
        13.             source.onopen = function (event) {    
        14.                 document.getElementById('OutputDiv').innerHTML += 'Connection Opened.<br>';    
        15.             };    
        16.             source.onerror = function (event) {    
        17.                 if (event.eventPhase == EventSource.CLOSED) {    
        18.                     document.getElementById('OutputDiv').innerHTML += 'Connection Closed.<br>';    
        19.                 }    
        20.             };    
        21.             source.onmessage = function (event) {    
        22.                 document.getElementById('OutputDiv').innerHTML += event.data + '<br>';    
        23.             };    
        24.         }    
        25.     </script>    
        26. </head>    
        27. <body onload="initialize()">    
        28.     <form id="form1" runat="server">    
        29.         <div id="OutputDiv">    
        30.         </div>    
        31.     </form>    
        32. </body>    
        33. </html>   
          Run the Application
          It will go updated until one minutes then close the connection as I define.


          Thus we learned that the Server-Sent Events APIs in HTML5 are an interesting lightweight and refactoring friendly alternative to WebSockets. It's uni-directional, so the client needs to use XMLHttpRequest to communicate client-to-server.