DEV Community

Cover image for Server side events using nodeJS
devashishSarmah
devashishSarmah

Posted on

Server side events using nodeJS

Server-Sent Events (SSE) is a technology based on HTTP. On the client-side, it provides an API called EventSource (part of the HTML5 standard) that allows us to connect to the server and receive updates from it.

Let's create a simple chat system

First, we are gonna create a new nodeJS project

Let's name it sse-server

Now, let's initiate npm to install some dependencies

Initiate NPM

We are gonna add express, body-parser and cors

NPM Install command

In index.ts

  • Configure the middleware
import express from 'express'; import bodyParser from 'body-parser'; import cors from 'cors'; const app = express(); app.use(cors()); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); 
Enter fullscreen mode Exit fullscreen mode
  • Specify the PORT
const PORT = 3000; 
Enter fullscreen mode Exit fullscreen mode
  • Declare and initialise the required variables
// Contains the connected clients info let clients: any[] = []; // Contains the messages of the network const messages: any[] = []; 
Enter fullscreen mode Exit fullscreen mode
  • Create a endpoint where the clients will subscribe to events
app.get('/messages', (request: any, response: any) => { const headers: any = { 'Content-Type': 'text/event-stream', Connection: 'keep-alive', 'Cache-Control': 'no-cache' }; response.writeHead(200, headers); const data: string = `data: ${JSON.stringify(messages)}\n\n`; response.write(data); const clientId = (request.query.id ?? 'guest') + '_' + Date.now(); const newClient: any = { id: clientId, response }; clients.push(newClient); request.on('close', () => { console.log(`${clientId} Connection closed`); clients = clients.filter((client: any) => client.id !== clientId); }); }); 
Enter fullscreen mode Exit fullscreen mode
  • A function to notify whenever a new message arrives in the network
const notifyMessageToAllUsers = (userIdWithoutUnderscore: string) => { clients .filter( (client: any) => String(client.id).split('_')[0] != userIdWithoutUnderscore ) .forEach((client: any) => { client.response.write(`data: ${JSON.stringify(messages)}\n\n`); }); }; 
Enter fullscreen mode Exit fullscreen mode
  • Finally an endpoint to push messages to the network
app.post('/message', (request, response) => { if ( request.query.id && request.body && request.body.message && String(request.body.message).trim() ) { messages.push({ user_id: request.query.id, message: request.body.message.trim() }); notifyMessageToAllUsers(String(request.query.id)); response.send({ status: 200, error: 'Message Sent Succesfully' }); } else { response.send({ status: 400, error: 'Bad Request' }); } }); 
Enter fullscreen mode Exit fullscreen mode
  • let's start the server
app.listen(PORT, () => { console.log(`Server is listening at http://localhost:${PORT}`); }); 
Enter fullscreen mode Exit fullscreen mode
$ npm start 
Enter fullscreen mode Exit fullscreen mode

Server console

$ Server is listening at http://localhost:3000 
Enter fullscreen mode Exit fullscreen mode

For pushing a message to the network

$ curl --location --request POST 'http://localhost:3000/message?id=1234' \ --header 'Content-Type: application/json' \ --data-raw '{ "message": "Hi" }' 
Enter fullscreen mode Exit fullscreen mode

To listen to the messages

curl --location --request GET 'http://localhost:3000/messages' \ --header 'Accept: text/event-stream' 
Enter fullscreen mode Exit fullscreen mode

After subscribing to the endpoint, we should be able to see the message that was pushed earlier

$ data: [{"user_id":"1234","message":"Hi"}] 
Enter fullscreen mode Exit fullscreen mode

Conclusion

SSE is very powerful in terms of receiving events from the server to achieve real-time behaviour in the client. But it can get very expensive if it's not implemented efficiently.

Thanks for Reading!

Thanks for reading, I hope you enjoyed it!

Top comments (0)