A quick intro to Server-Sent Events (SSE)
This is a very quick look into Server-Sent Events (SSE). This is a cool feature of HTML 5 that allows you to stream data from a server into a client in real-time.
I will only touch the surface of Server-Sent Events in this article, I just wanted to provide the basic idea and some working code for you to play with.
Basic idea
With most clients you generally need to make a request for data. For example, in the FlySpy application I delved into recently you need to make a request (HTTP) to the simple REST API to receive a list of events. This has pros and cons. It's a simple (stateless) approach, but it means you need to poll the server, and the server might have no events to send you, and that wastes bandwidth and battery life on the client.
It would be great if the server sent an event to the client as soon as that event was available. There are systems that can do this, and I recently described a simple project with Ably. Ably provides the infrastructure to deliver real-time events to a web or other client.
You can however also stream events to a client using Server-Sent Events.
So, without further ado, let's dive into some code...
Server
Here's a simple server that delivers real-time events. In my simple example I just sent the time every second:
const express = require("express");
const app = express();
app.use(express.static("public"));
app.get("/", (request, response) => {
response.sendFile(__dirname + "/views/index.html");
});
app.get("/stream", (req, res) => {
res.setHeader("Content-Type", "text/event-stream");
sendTime(res);
});
const listener = app.listen(process.env.PORT, () => {
console.log("Your app is listening on port " + listener.address().port);
});
function sendTime(res) {
const t = new Date().toString();
res.write("data: " + t + "\n\n");
setTimeout(() => sendTime(res), 1000);
}
There's an endpoint that streams data called /stream
. Looking at the code:
app.get("/stream", (req, res) => {
res.setHeader("Content-Type", "text/event-stream");
sendTime(res);
});
You can see that all this does is set the response header to a type text/event-stream
and then calls a function sendTime()
. The function sendTime()
is worthy of some more explanation. What it does is very simple, it sends the current time back to the client. There are a couple of things that are important to note though. First is this is a function that calls itself every second. The other thing to note is you need to terminate data sent back to the client with \n\n
.
Client
Let's take a look at the client code:
!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="A cool thing made with Glitch" />
<title>Server-Sent Events</title>
<script src="/script.js" defer></script>
</head>
<body>
<h1>Server-Sent Events</h1>
<p id="time">Time waits for no man...</p>
</body>
</html>
Well, pretty much all this does is provide a paragraph as a placeholder for data and calls some JavaScript:
const sse = new EventSource("/stream");
sse.onmessage = message => {
document.getElementById("time").innerHTML = message.data;
};
Oh, that's interesting. There's this new EventSource
object built into the browser engine - we'll have some of that real-time goodness thanks very much! There's also a simple callback that gets called when data arrives. All the code does is add that inbound data to the tagged paragraph element. Couldn't be easier! We are now displaying data in real-time - how funky is that!
Live demo on Glitch
Before I leave you, just to prove this all works, I hosted the project on Glitch. Feel free to grab (or remix) the project. You can see the live demo for yourself. OK so I had a complete failure of imagination there by just displaying the time...
There are probably other ways you could do this, but I will be coming back to SSE later with other projects (and of course Ably projects too), so treat this as a good first step.
Hope you find this useful and have fun using SSE in your own projects.