Detect Active Users in Angular Using NestJs and Socket.IO

Detect Active Users in Angular Using NestJs and Socket.IO

Sunny Sun Lv4

A comparison between Socket.IO and SignalR

I wrote an article titled “Detect Active Users in Angular App Using SignalR ” a couple of years ago. It wasn’t a long time ago, but technology has evolved quickly. In the world of real-time web apps, Socket.IO is emerging.

SignalR and Socket.IO share many similarities. Both are designed for real-time bidirectional communications between web client and server and use WebSocket as the default transport protocol.

Similarities aside, SignalR is part of the .Net ecosystem, and Socket.IO is built for NodeJS. But in practice, how different is Socket.IO compared with SignalR? What are the pros and cons?

To answer those questions, I rewrote the sample app in the previous article using NestJS and Socket.IO.

Let me show you how this experiment goes.

Jump ahead:

Overview

The following diagram illustrates the technology stack used in this contrived example. Reading my previous blog post, you will find that we use NestJS/Socket.IO instead of .Net Core/SignalR.

Architecture

Setup a WebSocket Server with NestJs

NestJS provides the WebSocket module, which supporting two WebSocket platforms (Socket. IO and ws ) out-of-the-box. In this article, we will use Socket.IO.

To get started, let’s create a new NestJS app and install the necessary dependencies.

1
2
3
nest new nest-waiting-room   
cd nest-waiting-room
npm i --save @nestjs/websockets @nestjs/platform-socket.io

After setting up the NestJS app skeleton, we must add a Gateway for the new app.

Configure NestJS Gateway

Gateway is introduced in NestJS as a platform-agnostic interface to web socket platforms. We can generate a gateway with NestJS CLI as below.

1
2
3
4
5
6
7
8
nest g gateway app

The generated gateway class looks like this:

@WebSocketGateway()
export class AppGateway implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect {
....
}

Please note that the class is decorated with the @WebsocketGateway() which gives us access to the web socket functionality.

We also implement 3 lifecycle hooks: OnGatewayInit, OnGatewayConnection and OnGatewayDisconnect . They are self-explanatory from their name.

CORS must be enabled as below to allow the angular client to access the gateway from different domains.

@WebSocketGateway({ cors: true })

Receive and Broadcast Messages with Socket.IO

The core of the Gateway class is to handle incoming and outgoing event messages.

To listen to incoming messages, we use @SubscribeMessage decorator.

To send an Event to all connected clients, you will need to use the WebSocketServer decorator and use the native WebSocket instance to emit a message:

1
2
@WebSocketServer() server;// Boardcast message to all connected clients  
this.server.emit('patientList', activeUsers.map(x=> x.userName));

Manage the user session data with Cache Manager

Like the SignalR version, we use an in-memory cache to store the state. This is mainly for illustration. In a real-world project, consider persisting the state into a database or Redis, to make it more scalable.

The user session data is managed by the UserSessionCache class. UserSessoinCache Class is built on top of Cache Manager . It exposes CRUD operations for the user session data.

When updating the cache data, we set this sample app’s expiration time to 60 minutes.

When the user session data is cached, we also update the lastConnectedTime property. If it’s 60 seconds more than the current time, we assume the user has disconnected.

Angular Client

To use the Socket.IO client in Angular, we need to install ngx-socket-io , an Angular wrapper, over Socket.IO client libraries.

1
npm i @ngx-socket-io --save

In App.module.ts, we declare the socket server config as below.

1
const config: SocketIoConfig = { url: 'http://localhost:3000', options: {} };

We also need to import SocketIoModule in AppModule. This will initialize the client connection to the socket server whenAppModule loads.

1
2
3
4
imports: [  
...,
SocketIoModule.forRoot(config)
]

We create a WebScoketService to handle the client-side events:

In the above code snippet, userPing function invokes the socket.emit to send the event to the socket server. This function is called in the waitingroomAngular component every second so the server will be aware that the user is active on the page.

1
2
3
this.interval = setInterval(() => {  
this.service.userPing(this.userName);
}, 1000);

The waiting room page also has an activeUsers$observable. It subscribes from the socket.IO server patientList event. Thus, any change of connected users will be shown in real-time.

The final result is identical to the SignalR version!

SignalR App

Socket.IO vs. SignalR

Overall, I like Socket.IO. It’s surprisingly straightforward to set up and has all the required features.

Compared with the implementation using SignalR, I only need to write half the code to get the same features for both client and server. That’s proof that much less boilerplate code is needed when using Socket.IO.

Although we only use the most basic functionalities in this simple example, it’s worth highlighting that Socket.IO provides many other important features. It includes Rooms, an arbitrary channel that can be used to broadcast events to a subset of clients. It also supports load balancing and data streaming.

Summary

Socket.IO enables bi-directional communication between web clients and servers. It adds a nice abstraction on top of WebSocket and exposes enough but not overly complicated APIs to get work done.

Another major benefit of using Socket.IO is the active and vibrant NodeJS community and ecosystem. I prefer to use NestJS/Socket.IO for future projects unless the project is based on the .Net platform.

The source code for the Angular client sample is here , and the NestJS sample can be found here .

  • Title: Detect Active Users in Angular Using NestJs and Socket.IO
  • Author: Sunny Sun
  • Created at : 2022-01-07 00:00:00
  • Updated at : 2024-08-16 19:46:17
  • Link: http://coffeethinkcode.com/2022/01/07/detect-active-users-in-angular-using-netsjs-and-socket-io/
  • License: This work is licensed under CC BY-NC-SA 4.0.