Javascript demo of Server Sent Events SSE tutorial (EventSource)

5 Apr 2019 | Javascript demo of Server Sent Events SSE tutorial (EventSource) |

EventSource Browser Compatibility chart

This  easy to follow tutorial will show you how to stream server data  (sometimes called SSE’s, Server Sent Events) , in real-time to your browser. Using  Javascript’s EventSource API  interface we can seamlessly update and display on a web page real-time  server-sent data  all without the complexities of setting up a web socket server. There’s a capability in virtually all modern HTML5 browsers (and really who in 2019 isn’t using a modern browser? only older versions of IE have  an issue).

If you need to use it with IE there’s a bunch of available Poly-fills If you are using browserify , you just have to require this package in your main module…There’s many alternative Poly-fills like this IE EventSource Polyfill .  Want to see it in action? , just skip to the demo section below.

This is a successor to the old method of long-polling used to fetch server data on a polling (period) basis.

The EventSource API  interface provides a lot of benefits for one-way (server to browser) data streaming, yet is much, much simpler to implements than web sockets . Websockets are a  richer and more complex protocol to perform bi-directional, full-duplex communication , whereas SSE’s are a more simplified one-way HTTP-based communication channel that has a bunch practical applications, and is much easier to implement, which I’ll outline in this blog post.

Demo examples of  using Server Sent Events

Simulated “Live”Stock Ticker

Some simple demo examples of Server Sent Events.

Also all the code below is up on my GitHub Page under my Javascript Repo .. under Javascript_SSEvents .

 

Basic JavaScript Event Source  code

EventSource Communications Flow

There’s two parts to the event Source code, first, we will configure the browser to bind to  the server generated message events. This is done using the JavaScript’s EventSource interface . Server Sent Events are sent using regular HTTP (or HTTPS), the advantage of this is that any web server that serves HTTP/1.1 or  HTTP/2 or higher  is already compatible and no special server implementation is necessary.

Web Sockets on the other hand, require full-duplex connections and new Web Socket servers to handle the protocol. In addition, Server-Sent Events have a variety of features that WebSockets lack by design such as automatic re-connection, event IDs, and the ability to send multiple named events in one data page.

Let’s set up the simplest example:

  1. Check that the browser supports EventSource using if (!!window.EventSource)
    1. For IE browser compatibility  simply include the EvenSource Polyfill 
  2. instantiate the EventSource object , new EventSource(some_url) , some url is the server script generating the events.
  3. Bind various handlers, such as open, message, and error to deal with each of those message situations.
var eSource;  //define my global eventSource Object

if (!!window.EventSource)  //Check for Browser feature compatibiliity
 {
  var eSource= new EventSource('my_sse_server.php');  //instantiate the Event source
} else {
  alert("You're browser does not support EventSource needed for this page ");
  // Fallback method perhaps you can use old-school XHR polling
}

//Now bind various Events , Message, and Error to this event
eSource.addEventListener('open', function(e) {
  console.log("Connection was opened.")
}, false);


eSource.addEventListener('message', function(e) {
  console.log(e.data);
}, false);


eSource.addEventListener('error', function(e) {
  if (e.readyState == EventSource.CLOSED) { 
    console.log("Connection was closed. ");
  }
}, false);

When messages are sent from the server, and they are properly formed the message  handler is triggered, and the data comes inside the e.data  object.

The Javscript code will automatically re-connect after the default 3 seconds, this re-connection period can be adjusted see EventSource API for details.

Event Message Format (JSON)

The event message which is available inside your e.data object  is sent in plaint-text  served with a text/event-stream Content-Type. In its basic form, the response should contain a “data:” line, followed by your message, followed by two “\n” characters to end the stream.

data: First line Message  \n
data: Second line Message \n
data: Event Source Final Line Message \n\n

for multiple line messages simply use multiple data: lines,  just make each line have \n (new line char) and only the final line in the message have \n\n to indicate end of stream .  Sending back JSON data is pretty easy , just break up your JSON data by lines with the proper format of \n . Below is a sample Geo Coordinate JSON data.

data: { \n
data:   "type": "Feature", \n
data:   "geometry": { \n
data:     "type": "Point", \n
data:     "coordinates": [125.6, 10.1] \n
data:   }, \n
data:   "properties": { \n
data:     "name": "Dinagat Islands" \n
data:   } \n
data: } \n\n

and back in your JavaScript event handler code you can parse the JSON as follows:

<script>

source.addEventListener('message', function(r) {
  var data = JSON.parse(e.data);   //turning the JSON data message back to JSON variable
  console.log(data.id, data.msg);
}, false);

</script>

That’s about it for the JavaScript piece. There’s a few more message attributes that allow you some more control, for example, you can associate an ID with the message data, that will allow the browser to track via the e.lastEventId property which is useful should their be an interruption from with the server connection. Also you can set the connection re-try period from the default 3 seconds to another value. And for convenience and filtering you can bind to different named events from the same stream using a unique event: name attribute.

retry: 10000\n
event: StockQuotes\n
id: 123\n
data: STOCK: GOOG\n
data: PRICE: 550.20\n\n
id: 456\n
data: STOCK: TSLA\n
data: PRICE: 273.20\n\n
id: 787\n
data: STOCK: BA\n
data: PRICE: 393.20\n\n
event: MarketTime\n
data: NASDAQ: 11:46\n\n 

By naming events different in the same stream you can associate specific event handlers in your code like the code shown below.

source.addEventListener('StockQuotes', function(e) {
   console.log(e.data);
}, false);

source.addEventListener('MarketTime', function(e) {
   console.log(e.data);
}, false);

The server piece in PHP or NodeJS or Golang ..

I’ll write this server in my preferred language of PHP , but really any HTTP server compatible language will  work. There’s a good example here of using a NodeJS server to send out the events.  I also created a simple Go Lang SSE example 

<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache'); // recommended to prevent caching of event data.

/**
 * Constructs the SSE data format and flushes that data to the client.
 *
 * @param string $id id of this connection.
 * @param string $message Line of text that should be transmitted.
 */
function sendMsg($id, $message ) {
  echo "id: $id" . PHP_EOL;
  echo "data: $message" . PHP_EOL;
  echo PHP_EOL;
  ob_flush();  
  flush(); //don't  forget  to  flush  so  the  server  sends  it  out
} 



//NO Need to LOOP this message as browser will re-connect every 3 seconds
sendMsg( time() , 'server time: ' . date("h:i:s", time()));

?>

As you can see the server script is  simple. This one just outputs a time string, but really any other type of textual data can be produced. Also note no need to write loops in the server component,  because of  the SSE protocol an automatic re-connection will be triggered, re-starting a new PHP script every 3 seconds, this is adjustable, see the retry: nn message data format above..

SSE Weather Page

Try it out yourself, Run it in chrome and press F12 (developer options), click on Network link and click on the server script name, notice the EventStream  and you will see periodic calls to the PHP script as the re-connection occurs.

A word of caution, too many PHP requests from  too many open connections , may exhaust Apache handle limits, if you’re planning to do this with thousands of browser instances, you’re better to use something like NodeJS , because of its single-threaded nature its much less resource intensive..

Complete code and demos check out my GitHub Page under my Javascript Repo .. under Javascript_SSEvents

Conclusion

CPU/RAM/DISK

The applications for SSE are endless, while you may not want to write a multi-player game that requires fast  low latency two-way communications (web sockets are better for that), for a wide range of other applications where you want to update data in the  browser dynamically , easily and quickly SSE is the perfect companion.

5 (100%) 1 vote[s]

2 thoughts on “Javascript demo of Server Sent Events SSE tutorial (EventSource)

  1. Reply Rossan Ugleriz Apr 5,2019 4:17 pm

    Neat how did you get the numbers to scroll Like that?

Leave a Reply