Chat Application with Angular and Socket.IO

Introduzione

Utilizzeremo RxJS, Angular, express (Node.js) &Socket.IO per fare una chat application. Avremo modo di vedere quanto possa essere utile RxJS in questo scenario. Allo scopo di rendere le cose lisce e facili, useremo Angular CLI per generare la struttura di base del client e ottenere un boilerplate per la più semplice applicazione Angular funzionante. Sul back-end useremo Node.js con express e Socket.IO. Il ragionamento dietro a questo è che Socket.IO è molto facile da impostare e lavorare. Inoltre, fornisce librerie sia lato server che lato client. Socket.IO usa principalmente il protocollo WebSocket per abilitare la comunicazione bidirezionale in tempo reale.

Se vuoi saltare direttamente alla parte in cui usiamo RxJS per gestire i messaggi di chat clicca qui.

Iniziamo!

Socket.IO server setup

Se non avete installato Angular CLI potete installarlo abbastanza facilmente:

npm i -g @angular/cli

Imposta la struttura delle cartelle

Per mantenere le cose pulite creeremo una nuova cartella rxjs-chat per il nostro piccolo progetto. Dovrebbe servire come cartella principale per le applicazioni Angular e Socket.IO.

Creiamo un’applicazione Angular di base usando Angular CLI. Nella cartella del nostro progetto lanciate il vostro terminale preferito ed eseguite il seguente comando:

ng new rxjs-chat

Dategli un po’ di tempo. Dopo aver finito di creare la struttura di base e di installare i pacchetti npm, rinomineremo la cartella del progetto Angular appena creata in client. Dopo di che, nella stessa cartella principale creiamo la cartella server per il nostro server Socket.IO. Ora abbiamo due cartelle all’interno della nostra cartella rxjs-chat:

  • client – app client Angular
  • server – presto sarà il server Socket.IO di Node
Installazione di pacchetti locali

Nella cartella server genereremo il file package.json eseguendo il seguente comando:

npm init -y

Dopo di che installeremo le nostre dipendenze e le salveremo in package.json:

npm install express socket.io --save

Nella stessa cartella creeremo il file index.js per la nostra app server. Il contenuto del file dovrebbe essere il seguente:

Creiamo un’istanza di express e la memorizziamo nella variabile app. Dopo di che creiamo il server con il modulo http. Poi passiamo express al metodo http.Server(). Express servirà come gestore per le richieste al nostro server. In cambio otteniamo l’istanza del server che memorizziamo nella variabile server.

Nelle prossime due linee di codice leghiamo il socket.IO con il nostro http server:

let socketIO = require('socket.io');

let io = socketIO(server);

Dopo di che ascoltiamo l’evento di connessione del socket.IO e registriamo quando un utente ha stabilito una connessione con il server. Infine avviamo il server e ascoltiamo su una data porta, nel nostro caso è la porta 3000.
Avviamo effettivamente il nostro server eseguendo quanto segue nella cartella del server:
node index.js
Di conseguenza si dovrebbe ottenere il seguente messaggio: “avviato sulla porta: 3000”.

Collegamento a Socket.IO

Abbiamo un server in esecuzione sulla porta 3000. Ora è il momento di vedere come possiamo connetterci al server dalla nostra app Angular. Per questo avremo bisogno di installare la libreria client Socket.IO. Eseguiremo il seguente comando nella nostra cartella client:

npm install socket.io-client --save

Mentre ci siamo eseguiamo l’app Angular tramite Angular CLI:

ng serve -o

Ora abbiamo la nostra app in esecuzione. Possiamo vedere che il nostro browser predefinito ha appena aperto una nuova scheda che punta a localhost. Ecco perché abbiamo usato l’argomento -o per aprire il browser.

Creazione del servizio per la comunicazione con il server

Lo chiamerò chat.service.ts app.chat.service.ts e lo metterò dentro la cartella src. Il servizio sarà il più semplice possibile per ora:

Aggiungere il servizio ai provider del modulo

Inoltre, aggiungiamo il nostro ChatService alla lista dei provider all’interno di AppModule nel file app.module.ts:

Iniezione del servizio nel nostro componente

Finalmente, stiamo per importare e usare il servizio all’interno del nostro app.component.ts:

import { ChatService } from './app.chat.service';

E inietteremo il ChatService nel nostro costruttore:

constructor(chatService: ChatService) { }

Come risultato abbiamo il seguente file:

Se tutto è andato come previsto dopo aver salvato le modifiche dovresti vedere il messaggio ‘user connected’ nel terminale dove hai avviato node app:

$ node index.js
started on port: 3000
user connected

Dunque, possiamo dire che siamo finalmente riusciti a connetterci al nostro server Socket IO. Ora è il momento di inviare effettivamente dei dati tramite gli eventi Socket IO.

Inviare un messaggio a Socket.IO

È ora di migliorare il nostro finora semplice ChatService con un’opzione per inviare un messaggio al server:

Perché questo funzioni dobbiamo usare sendMessage() dal nostro AppComponent:

Finalmente, forniamo all’utente un semplice input di testo e un pulsante per poter inviare un messaggio:

Perché tutto questo funzioni dobbiamo ascoltare sul server l’evento ‘new-message’ che abbiamo emesso dal ChatService:

socket.on('new-message', (message) => {
console.log(message);
});

Ora il nostro index.js assomiglia a questo:

Se volete giocare con il codice potete trovarlo sul mio repo GitHub – rxjs-chat.

Comunicare con altri utenti

Per far sì che il nostro messaggio venga trasmesso ad altri utenti tutto quello che dobbiamo fare è cambiare il console.log(message) interno del nostro callback dell’evento ‘new-message’ in io.emit(message):

E cosa fa io.emit()? In parole povere invia un evento a tutti quelli connessi al server.

Comunichiamo con il nostro server tramite ChatService. Aggiungeremo un nuovo metodo al nostro servizio per questo scopo – getMessages. Restituirà un Observable che creeremo con il metodo Observable.create(). Ogni volta che il socket riceve un nuovo messaggio useremo observer.next() per inoltrarlo agli osservatori.

Dopo di che ci iscriveremo a questo Observable dal nostro AppComponent:

Abbiamo creato un nuovo messages array dove memorizzeremo i messaggi ricevuti dal server. Dovremo mostrare questi messaggi nel nostro template. Questo è un caso d’uso perfetto per ngFor:

.