DEV Community

Cover image for Real-Time Applications Node.js and Angular with Socket.IO
Kafeel Ahmad (kaf shekh)
Kafeel Ahmad (kaf shekh)

Posted on

3

Real-Time Applications Node.js and Angular with Socket.IO

In today’s fast-paced digital world, real-time communication has become a crucial aspect of modern web applications. Whether it’s live chat, notifications, or real-time data updates, providing instant feedback to users enhances the overall user experience. In this blog post, we will explore how to implement real-time communication using Socket.IO with Angular and Node.js. By the end of this tutorial, you will have a solid understanding of how to set up a real-time application that can handle client-server communication efficiently.

What is Socket.IO?
Socket.IO is a JavaScript library that enables real-time, bidirectional, and event-based communication between web clients and servers. It builds on top of the WebSocket protocol, providing additional features like automatic reconnection, multiplexing, and error handling, which make it a powerful tool for real-time applications.

WebSockets vs. Socket.IO:
WebSockets: A protocol that enables low-latency, full-duplex communication channels over a single TCP connection.
Socket.IO: An abstraction layer on top of WebSockets that provides additional functionality, making it easier to implement real-time features.
Project Initialization
To get started, we’ll set up a project structure with separate client and server directories.

Creating Directories:

client: This will contain the Angular application.
server: This will contain the Node.js application.
Initializing Angular Application:

ng new client

cd client

npm install socket.io-client
Enter fullscreen mode Exit fullscreen mode

Initializing Node.js Application:

mkdir server

cd server

npm init -y

npm install express cors socket.io

npm install --save-dev nodemon
Enter fullscreen mode Exit fullscreen mode

Setting Up nodemon:

Update the package.json file to use nodemon for automatically restarting the server on file changes.

{
  "scripts": {
    "start": "node index.js",
    "dev": "nodemon index.js"
  }
}
Enter fullscreen mode Exit fullscreen mode

Setting Up Socket.IO on the Client with Observables
Integrating Socket.IO-client with Angular using Observables:

Create an Angular service to manage Socket.IO connections and use observables to handle events.

// src/app/services/socket.service.ts
import { Injectable } from '@angular/core';
import { io, Socket } from 'socket.io-client';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root',
})
export class SocketService {
  private socket: Socket;

  constructor() {
    this.socket = io('http://localhost:3000');
  }

  emit(event: string, data: any) {
    this.socket.emit(event, data);
  }

  on(event: string): Observable<any> {
    return new Observable((observer) => {
      this.socket.on(event, (data) => {
        observer.next(data);
      });

      // Handle cleanup
      return () => {
        this.socket.off(event);
      };
    });
  }
}
Enter fullscreen mode Exit fullscreen mode

Establishing a Connection:

Use the SocketService in your components to establish a connection and subscribe to events.

// src/app/app.component.ts
import { Component, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs';
import { SocketService } from './services/socket.service';
import { FormsModule } from '@angular/forms';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  standalone: true,
  imports: [FormsModule],
})
export class AppComponent implements OnDestroy {
  private messageSubscription: Subscription;
  messages: string[] = [];
  newMessage: string = '';

  constructor(private socketService: SocketService) {
    this.messageSubscription = this.socketService
      .on('message')
      .subscribe((data) => {
        this.messages.push(data.text);
      });
  }

  sendMessage() {
    this.socketService.emit('message', { text: this.newMessage });
    this.newMessage = '';
  }

  ngOnDestroy() {
    this.messageSubscription.unsubscribe();
  }
}
Enter fullscreen mode Exit fullscreen mode

Modifying the HTML Template:

Update app.component.html to include an input field for sending messages and a display area for received messages.

<!-- src/app/app.component.html -->
<div>
  <h1>Real-Time Chat</h1>
  <div>
    <input [(ngModel)]="newMessage" placeholder="Enter your message" />
    <button (click)="sendMessage()">Send</button>
  </div>
  <div>
    <h2>Messages:</h2>
    <ul>
      @for ( message of messages; track $index) {
      <li>{{ message }}</li>
      }
    </ul>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Setting Up Socket.IO on the Server
Setting Up an Express.js Server:

// server/index.js
const express = require("express");
const http = require("http").createServer();
const io = require("socket.io")(http, {
  cors: {
    origin: "*",
  },
});
const cors = require("cors");

const app = express();
const port = 3000;

// Enable CORS for all requests
app.use(cors());

// Define a route handler for the root path
app.get("/", (req, res) => {
  res.send("Hello, world!");
});

io.on("connection", (socket) => {
  console.log("New client connected");
  socket.on("disconnect", () => {
    console.log("Client disconnected");
  });
});

// Start the server
http.listen(port, () => {
  console.log(`Server is running at http://localhost:${port}`);
});
Enter fullscreen mode Exit fullscreen mode

Handling Client Connections and Disconnections:

io.on('connection', (socket) => {
  console.log('New client connected');

  socket.on('message', (data) => {
    console.log('Received message:', data);
    io.emit('message', data); // Broadcasting the message
  });

  socket.on('disconnect', () => {
    console.log('Client disconnected');
  });
});
Enter fullscreen mode Exit fullscreen mode

Emitting Events
Emitting events is a fundamental part of Socket.IO’s event-driven architecture. Here’s how you can emit events from the client to the server and handle them on the server.

Client Side:

  sendMessage() {
    this.socketService.emit('message', { text: this.newMessage });
  }
Enter fullscreen mode Exit fullscreen mode

Server Side:

socket.on('message', (data) => {
console.log('Received message:', data);
});
Broadcasting Events
Broadcasting allows the server to send messages to all connected clients. This is useful for real-time updates like chat messages or notifications.

Server Side:

socket.on('message', (data) => {
  console.log('Received message:', data);
  io.emit('message', data); // Broadcasting the message to all clients
});
Enter fullscreen mode Exit fullscreen mode

Client Sode:

constructor(private socketService: SocketService) {
this.messageSubscription = this.socketService.on('message').subscribe((data) => {
this.messages.push(data.text);
});
}
Handling Disconnections
Handling disconnections ensures that your application can gracefully manage client departures, maintaining the integrity of real-time interactions.

Server Side:

socket.on('disconnect', () => {
  console.log('Client disconnected');
});
Enter fullscreen mode Exit fullscreen mode

Client Side:

You don’t need additional code on the client side for disconnections, as Socket.IO handles this automatically.

Conclusion
In this blog post, we covered the basics of implementing real-time communication using Socket.IO with Angular and Node.js. We discussed project initialization, setting up Socket.IO on both the client and server, emitting and broadcasting events, and handling disconnections. Real-time communication is a powerful feature that can significantly enhance user experience, and Socket.IO makes it easy to implement.

By following this guide, you should now have a working real-time application. Feel free to explore further features of Socket.IO and experiment with more complex use cases

Image of Datadog

Create and maintain end-to-end frontend tests

Learn best practices on creating frontend tests, testing on-premise apps, integrating tests into your CI/CD pipeline, and using Datadog’s testing tunnel.

Download The Guide

Top comments (0)

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay