Realtime data streaming using server-sent events(SSE) with react.js and node.js
Tags: javascript, tutorial, react, node
Published: 2022-03-12 01:45:42

We live in a world where real-time data streaming has become paramount. Real-time data streaming has become a necessity in modern applications because it keeps users notified immediately an event happens. But most of the communication we see on the internet involves a client application making a request to the server which in turn processes the request and send back response to the client. This takes time to process and there are scenarios where a server needs to send data to the client without the client necessarily initiating a request. 

This could be done using long polling, websockets, webhooks or server-sent events. Examples of real-time applications include; instant messaging, notification system, online gaming, chat apps, videoconferencing, data streaming, sport updates, stock prices e.t.c. But our main focus in the article is Server-sent events.

_You can also read_

[Stream Processing Paradigm: Enabling Continuous Data Analysis and Transformation](https://dev.to/techfortified/stream-processing-paradigm-ena_bling-continuous-data-analysis-and-transformation-42ll)


**Video Tutorial**

_If you prefer to watch and learn an in-depth tutorial on how to implement server-sent events(SSEs) with react js and node js, here is a full video for you._

_Please don't forget to like, comment, subscribe to my youtube channel and share the video with your friends._

{% youtube d06PFSHfdzM %}

## Different techniques for client-server communication

Below are some of the techniques used for client server communication

**Polling** is a technique where the application repeatedly polls data from the server and if you are familiar HTTP protocol, it involves request/response format. It is a traditional technique used by the vast majority of AJAX applications. The trade off with polling is that it creates greater HTTP overhead.

**Long polling** is a technique in which if the server does not have the data available when a request is made from the client, the server holds the request open until data is available. The server responds when data becomes available, closes the connection and when the client receives the new data, it sends another request to the server again. This cycle is repeated endlessly until either of them closes the connection. The major drawback of this mechanism is once the server has sent the data; it cannot send further data until a new poll request arrives.

**WebSockets** is a communication protocol that provides full-duplex bi-directional, communication channel over a single TCP connection. This mechanism creates a two-way connection between the server and the client i.e the server can send data to the client and client can send data to the server as well This is great for things like chat apps, instant messaging e.t.c. 
However, sometimes you need some updates from the server without waiting for the client to repeatedly initiate requests. This includes; friends' online status updates, newsfeeds e.t.c

**Server-Sent Events** is an HTTP standard that enables a client application to automatically receive updates or event streams from the server once an initial connection has been established. It’s a server push technology that allows client apps to receive data transmission from the server via an HTTP connection and describes how servers can stream data to the client once an initial connection has been established.  Server-sent events (SSEs) are unidirectional in nature i.e., only the server can push updates to client. SSE is commonly used to send automatic updates or continuous data streams to a browser client.

The main difference between Server-Sent Events and long-polling is that SSEs are handled directly by the browser and the client app simply has to listen for messages.

SSE contained in the JavaScript EventSource API in order to open a connection to the server to continue receiving event streams. In server-sent events, automatic updates are sent to client rather than pulled from the client. 


_You can also read_

[Stream Processing Paradigm: Enabling Continuous Data Analysis and Transformation](https://dev.to/techfortified/stream-processing-paradigm-ena_bling-continuous-data-analysis-and-transformation-42ll)


## Server-sent events VS Websockets

**WebSockets** provide **bi-directional**, full-duplex communication. It creates a two-way channel where the client can send data to the server and the server can also send data to client. This enables a real-time communication in both directions. This makes it effective for cases like real-time chat apps, games etc. 

However, there are some scenarios where client apps don’t need to send data to server but only consumes from the server and this is where server-sent events(SSEs)  comes in. 

In SSEs, the communication is **unidirectional** i.e., the server continuously pushed event streams to the client once an initial connection has been established. Examples include; real-time notification systems, sport updates, stock prices, status updates, newsfeed, cryptocurrency updates e.t.c

**Server-sent Events implementation**

Server sent server can be implemented both server side and client-side environment.

**Client-side API**

The SSE client API is contained in the **EventSource** object. 
When using SSE, the browser will generate an instance of **EventSource** first to initiate a connection to the server.

In order to detect if a browser supports SSEs, use the code snippet below;

```
const url = "http://localhost:5000/stream"
//url can be your server url

if ('EventSource' in window) {
  let source = new EventSource(url)
}

```

**Note:** The **URL** above can be in the same domain as the current **URL** of the application or it can be cross domain as well. When the URL passed to the **EventSource** constructor is an absolute URL, its origin (scheme, domain, port) must match that of the server. 

When a cross-domain is passed as the url, you can specify a second _options _ parameter with **withCredentials** property to indicate whether to send the cookie & auth headers altogether or not as shown below.

```
const url = "http://localhost:5000/stream"
//url is your server url

if ('EventSource' in window) {
  let source = new EventSource(url, {withCredentials: true})
}

```

**Eventsource object events**

By default, there are three (3) events which include **message**, **open** and **error** to listen on.

- The **open** event indicates a successful connection between the server and the client.

- The **error** event handles an error connection between the server and the client.

- The **message** event is used to listen on live stream data emitted by the server after a successful connection.

SSEs are flexible enough that you can even define your own custom events on the server which you in turn listen on, on the client side. 

Below are the three (3) default event listeners with their callbacks.

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


```
source.addEventListener('open', function(e) {
  // successful connection.
}, false);
```


```
source.addEventListener('error', function(e) {
  // error occurred
}, false);
```

**EventSource object properties**

Some of the properties of the **EventSource** instance include;

- **readyState** e.g source.readyState
  
    - readyState value of 0 indicates connecting
    
    - readyState value of 1 indicates open
     
    - readyState value of 0 indicates closed
      
- **url** e.g source.url returns connection url

- **withCredentials** e.g source.withCredentials show whether or not **withCredentials** is true.
	

**EventSource object methods**

The **closed()** method can be called to close the connection e.g source.closed()


**Server-side implementation**

**SSE Data format** 

The SSE data sent by the server to the browser must be UTF-8 encoded text with the following HTTP header.

```
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
```


The information sent each time consists of several messages, and each message is separated by **\n\n**. Each message is composed of several lines of code internally, and each line should be written as follows.

[field]: value\n
The above field can take the following four values.

- **data ** indicates the payload to be sent.

- **retry** indicates the reconnection time in seconds and it's optional

- **event** can be a custom event e.g notification defaults to **message** when no event is passed

- **id** indicates the id of the data to be sent and it's optional


```
const emitSSE= (res, id, data) =>{
  res.write('id: ' + id + '\n');
  res.write("data: " + data + '\n\n');
  res.flush()
}

const handleSSE = (req, res) =>{
  res.writeHead(200, {
    'Content-Type': 'text/event-stream',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive'
  });
  const id = (new Date()).toLocaleTimeString();
  // Sends a SSE every 3 seconds on a single connection.
  setInterval(function() {
    emitSSE(res, id, (new Date()).toLocaleTimeString());
  }, 3000);

  emitSSE(res, id, (new Date()).toLocaleTimeString());
}



//use it

app.get("/stream", handleSSE)
```

**Using Server-sent events with React.js and Node.js**

Implementing server-sent events can be fairly simple but it gets confusing when you want target or send an event to a specific user as there is no clear way to exchange user data with the server.
But in the video tutorial below; we have addressed the issues of sending global events as well as targeting specific users.

In the video tutorial below, we are going to build and deploy a realtime twitter-like newsfeed using server-sent events(SSE) with react.js, node.js and mongodb from the scratch and deploy it on cpanel. 

This tutorial is for beginners and advanced programmers who wish to learn to implement the following;
1. How to implement SSE in react js  and node js application
2. How to broadcast data to all users using server-sent events
3. How to send data to a  specific or single user using server-sent events
4. How to implement LIKE button
5. API(Application Programming Interface)
6. React Hooks(useState, useContext, useReducer)
7. Hosting(Deployment) on cpanel

**Resources & Demo**

[Get the code on github](https://github.com/supatechie/react-node-sse)

[Demo test, check it out here](https://sse.techfortified.com/)

_You can also read_

[Stream Processing Paradigm: Enabling Continuous Data Analysis and Transformation](https://dev.to/techfortified/stream-processing-paradigm-enabling-continuous-data-analysis-and-transformation-42ll)

**Summary**

_Realtime data streaming has become a necessity in a standard modern application as this keeps your user notified of all the activities within your application. In this article, we discussed various techniques of client server communication and the need to go with server-sent events. Server-sent events(SSE) is a server push technology that enables a client to receive live stream updates from the server via a HTTP connection. It is lightweight and supported by most modern browsers and as a result, it's well suited for real-time automatic data stream from the server_

**Video Tutorial**

If you want to watch and learn an in-depth tutorial on how to implement server-sent events(SSEs) with react js and node js, here is a video for you.

_Please don't forget to like, comment, subscribe to my youtube channel and share the video with your friends._

{% youtube d06PFSHfdzM %}