Aplicație de chat cu Angular și Socket.IO

Introducere

Vom folosi RxJS, Angular, express (Node.js) & Socket.IO pentru a realiza o aplicație de chat. Vom avea ocazia să vedem cât de util poate fi RxJS în acest scenariu. În scopul de a face lucrurile netede și ușoare, vom folosi Angular CLI pentru a genera structura de bază a clientului și pentru a ne obține un boilerplate pentru cea mai simplă aplicație Angular de lucru. În back-end vom folosi Node.js cu Express și Socket.IO. Raționamentul din spatele acestui lucru este că Socket.IO este foarte ușor de configurat și de lucrat cu el. În plus, acesta oferă atât biblioteci de partea serverului, cât și de partea clientului. Socket.IO folosește în principal protocolul WebSocket pentru a permite comunicarea bidirecțională în timp real.

Dacă vreți să treceți direct la partea în care folosim RxJS pentru a gestiona mesajele de chat, faceți clic aici.

Să începem!

Socket.IO server setup

Dacă nu aveți Angular CLI instalat, îl puteți instala destul de ușor:

npm i -g @angular/cli

Set up folder structure

Pentru a păstra lucrurile curate, vom crea un nou folder rxjs-chat pentru micul nostru proiect. Acesta ar trebui să servească drept dosar rădăcină pentru aplicațiile Angular și Socket.IO.

Să creăm o aplicație Angular de bază folosind Angular CLI. În folderul proiectului nostru lansați terminalul preferat și rulați următoarea comandă:

ng new rxjs-chat

Dă-i puțin timp. După ce a terminat de creat structura de bază și de instalat pachetele npm, vom redenumi dosarul nou creat al proiectului Angular în client. După aceea, în același folder rădăcină vom crea folderul server pentru serverul nostru Socket.IO. Acum avem două dosare în interiorul dosarului nostru rxjs-chat:

  • client – aplicația client Angular
  • server – în curând serverul Socket.IO al lui Node
Instalarea pachetelor locale

În dosarul server vom genera pachetul.json prin rularea următoarei comenzi:

npm init -y

După aceea vom instala dependențele noastre și le vom salva în package.json:

npm install express socket.io --save

În același dosar vom crea fișierul index.js pentru aplicația noastră de server. Conținutul fișierului ar trebui să fie după cum urmează:

Creăm o instanță de expresie și o stocăm în variabila app. După aceea creăm serverul cu modulul http. Apoi trecem express la metoda http.Server(). Express va servi drept gestionar pentru cererile către serverul nostru. În schimb, obținem instanța serverului pe care o stocăm în variabila server.

În următoarele două linii de cod legăm socket.IO cu http-ul nostru server:

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

let io = socketIO(server);

După aceea, ascultăm evenimentul de conectare al socket.IO și înregistrăm o dată ce un utilizator a stabilit o conexiune cu serverul. În cele din urmă pornim serverul și îl ascultăm pe portul dat, în cazul nostru este portul 3000.
Să pornim efectiv serverul nostru rulând următoarele în folderul server:
node index.js
În consecință, ar trebui să primiți următorul mesaj: „pornit pe portul: 3000”.

Connecting to Socket.IO

Avem un server care rulează pe portul 3000. Acum este momentul să vedem cum ne putem conecta la server din aplicația noastră Angular. Pentru aceasta va trebui să instalăm biblioteca client Socket.IO. Vom rula următoarea comandă în folderul nostru client:

npm install socket.io-client --save

Dacă tot suntem aici, să rulăm aplicația Angular prin Angular CLI:

ng serve -o

Acum avem aplicația noastră care rulează. Putem vedea că browserul nostru implicit tocmai a deschis o nouă filă care arată către localhost. Acesta este motivul pentru care am folosit argumentul -o pentru a deschide browserul.

Crearea serviciului pentru comunicarea cu serverul

Îl voi numi chat.service.ts app.chat.service.ts și îl voi plasa în interiorul folderului src. Serviciul va fi cât se poate de simplu deocamdată:

Adaugarea serviciului la furnizorii modulului

De asemenea, haideți să adăugăm serviciul nostru ChatService la lista de furnizori din interiorul AppModule în fișierul app.module.ts:

Injectarea serviciului în componenta noastră

În cele din urmă, vom importa și utiliza serviciul în interiorul componentei noastre app.component.ts:

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

Și vom injecta ChatService în constructorul nostru:

constructor(chatService: ChatService) { }

Ca rezultat avem următorul fișier:

Dacă totul a decurs conform așteptărilor, după salvarea modificărilor, ar trebui să vedeți mesajul „user connected” în terminalul în care ați pornit node app:

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

Deci, putem spune că în sfârșit am reușit să ne conectăm la serverul nostru Socket IO. Acum este momentul să trimitem efectiv niște date prin intermediul evenimentelor Socket IO.

În trimiterea unui mesaj către Socket.IO

Este timpul să îmbunătățim serviciul nostru ChatService, până acum simplu, cu o opțiune de a trimite un mesaj către server:

Pentru ca acest lucru să funcționeze trebuie să folosim sendMessage() din AppComponent:

În cele din urmă, să punem la dispoziția utilizatorului o simplă intrare de text și un buton pentru ca acesta să poată trimite un mesaj:

Pentru ca toate acestea să funcționeze, trebuie să ascultăm pe server evenimentul „new-message” pe care l-am emis de la ChatService:

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

Acum, indexul nostru.js arată așa:

Dacă vreți să vă jucați cu codul îl puteți găsi în repo-ul meu GitHub – rxjs-chat.

Comunicarea cu alți utilizatori

Pentru ca mesajul nostru să fie transmis altor utilizatori tot ce trebuie să facem este să schimbăm console.log(message) în interiorul callback-ului evenimentului nostru ‘new-message’ în io.emit(message):

Și ce face io.emit()? În cuvinte simple, trimite un eveniment tuturor celor conectați la server.

Să comunicăm cu serverul nostru prin ChatService. Vom adăuga o nouă metodă la serviciul nostru în acest scop – getMessages. Aceasta va returna un Observable pe care îl vom crea cu metoda Observable.create(). De fiecare dată când socket-ul primește un mesaj nou, vom folosi observator.next() pentru a-l transmite observatorilor.

După aceea ne vom abona la acest Observable din AppComponent-ul nostru:

Am creat un nou messages array în care vom stoca mesajele primite de la server. Va trebui să afișăm aceste mesaje în șablonul nostru. Acesta este un caz de utilizare perfect pentru ngFor: