A simple guide to Server Sent Events (SSE) and EventSource
Real-time data delivery has become an essential requirement for many web applications. Whether it’s a live news update, real-time stock prices, or a chat application, the need to push data from the server to the client in real time has never been more prevalent.
What are Server Sent Events (SSE)?
Server Sent Events (SSE) is a server push technology enabling a client to receive automatic updates from a server via an HTTP connection(1). Unlike WebSockets, which is a two-way communication channel, SSE is a one-way channel from the server to the client, making it a perfect choice for applications that only require server-to-client updates.(2) (3)
Using EventSource to Handle SSE
EventSource is an API provided by modern browsers for receiving SSE. It establishes a persistent connection between the client and the server, allowing the server to send updates whenever necessary. With the EventSource api, we can handle the stream chunks (4) easily. The methods of EventSource are simply adoptable. Before proceeding with examples, I suggest you to read the API documentation on these sources. (5) (6)
Practical Implementation: Creating a Server and Client
We will create our server and client implementations. They will be basic examples in JavaScript, however you can easily implement to any language you prefer, or any JavaScript library / framework.
Let’s first create a folder called sse which will contain backend and frontend. At the end of this article, folder tree will look like this:
.
└── sse/
├── backend/
│ ├── server.js
│ ├── package.json
│ ├── package-lock.json
│ └── node_modules
└── frontend/
├── index.html
└── client.js
node and npm must be available in your system for this example.
1. Backend
Inside of sse folder, create a folder named backend, and inside of it, create server.js
file. We will create a Node.js server-side application using the Express.js framework. First execute following commands inside of backend
directory.
npm init -y
npm i express cors
Create a file named server.js
and copy/paste below code snippet in it.
I will not go into all the details in the code, but let’s focus on the route handler :
- It sets the response headers
Content-Type
totext/event-stream
andCache-Control
tono-store
. This indicates that the server will be sending a Server-Sent Event (SSE) stream and that the response should not be cached. If response’sContent-Type
is nottext/event-stream
, then fail the connection. (7–Article 15/3) - It then initialises a counter to 5 and sets up an interval that fires every 1 second.
- In each interval, it checks if the counter is greater than 0. If it is, it writes a new event named CustomEvent (it can be any string) to the SSE stream with the current time. If the counter is not greater than 0, it sends a closing event named Close (it can be any string too) and ends the interval.
2. Frontend
Create the frontend
folder inside of sse
. Then create index.html
which will have the basic markup and a ul
element, and client.js
file which is designed to work with the server-side code above. Below you will find both file codes:
EventSource Instance
In client.js
we first create the connection with new EventSource(...)
method, then we attach some events to listen. For details of the event handling, please have a look at this resource. (8)
source.addEventListener("CustomEvent", (event) => {...});
- This line adds an event listener for the "CustomEvent" event. When a "CustomEvent" event is received, it parses the event data from JSON to a JavaScript object, extracts the "time" property, and passes it toappendToList()
, which appends it to theul
in the document.source.addEventListener("Close", (event) => {...});
- This line adds an event listener for the "Close" event. When a "Close" event is received, it passes the event data toappendToList()
and closes theEventSource
connection.source.onerror = (error) => {...};
- This line sets an error handler for theEventSource
. If an error occurs, it logs the error message to the console. You can create you own error handling logic.
After running backend and frontend folders locally, here is what we will see on the page:
As you see, each second we get a chunk of data, then we close the stream. In the dev tools, we can also see the chunks in EventStream tab with the event names. How cool it is!
If you use an implementation of EventSource and not using native EventSource, you might see the tab stays empty. It is a known issue.(9) . There are some browser extensions to use the EventStream tab in those implementations which we will cover in the follow up article. (e.g. SSE viewer Chrome extension (10) .
Summarise
In this article, we’ve explored the concept of Server Sent Events (SSE) and how to use EventSource
to handle these events. We’ve seen how SSE, a server push technology, can establish a one-way communication channel from the server to the client, making it ideal for real-time data delivery in applications that only require server-to-client updates.
We’ve also delved into a practical implementation, creating a server and client using JavaScript. This hands-on approach not only helps us understand the theoretical aspects but also equips us with the practical skills needed to implement these concepts in real-world applications.
In the upcoming article, we will create another app with SSE, but this time it will support a request rather then GET
, since native EventSource
only accept GET
request.
Github Repo => https://github.com/omer-pon/sse-eventsource
Resources
- https://en.wikipedia.org/wiki/Server-sent_events#:~:text=Server-Sent%20Events%20(SSE),client%20connection%20has%20been%20established.
- https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events
- https://developer.mozilla.org/en-US/docs/Web/API/EventSource
- https://developer.mozilla.org/en-US/docs/Web/API/Streams_API/Using_readable_streams
- Same as 3
- https://html.spec.whatwg.org/multipage/server-sent-events.html#the-eventsource-interface
- Same as 7
- https://developer.mozilla.org/en-US/docs/Web/API/EventSource/message_event
- https://github.com/Azure/fetch-event-source/issues/3#issue-788078889
- https://chromewebstore.google.com/detail/sse-viewer/pkofiecpdokojdgoccnbfplkphbmppaf (Date of access: 23.04.2024)