Chatovací aplikace s Angular a Socket.IO

Úvod

Použijeme RxJS, Angular, express (Node.js) & Socket.IO k vytvoření chatovací aplikace. Uvidíme, jak užitečný může být RxJS v tomto scénáři. Pro hladký a snadný průběh budeme používat Angular CLI, které nám vygeneruje základní strukturu klienta a získáme tak kotel pro nejjednodušší fungující Angular aplikaci. Na back-endu budeme používat Node.js s Express a Socket.IO. Důvodem je to, že Socket.IO se velmi snadno nastavuje a pracuje s ním. Navíc poskytuje knihovny na straně serveru i klienta. Socket.IO používá především protokol WebSocket, který umožňuje obousměrnou komunikaci v reálném čase.

Pokud chcete přejít přímo na část, kde používáme RxJS pro zpracování zpráv chatu, klikněte sem.

Pustíme se do toho!

Socket.IO server setup

Pokud nemáte nainstalovaný Angular CLI, můžete jej nainstalovat poměrně snadno:

npm i -g @angular/cli

Nastavení struktury složek

Aby bylo vše čisté, vytvoříme pro náš malý projekt novou složku rxjs-chat. Ta by měla sloužit jako kořenová složka pro aplikace Angular a Socket.IO.

Vytvoříme základní aplikaci Angular pomocí Angular CLI. Ve složce našeho projektu spusťte svůj oblíbený terminál a spusťte následující příkaz:

ng new rxjs-chat

Dejte tomu trochu času. Po jeho dokončení vytvoření základní struktury a instalaci balíčků npm přejmenujeme nově vytvořenou složku projektu Angular na client. Poté ve stejné kořenové složce vytvoříme složku server pro náš Socket.IO server. Nyní máme uvnitř naší složky rxjs-chat dvě složky:

  • klient – klientská aplikace Angular
  • server – brzy Socket.IO server Node
Instalace lokálních balíčků

Ve složce server budeme generovat balíček.json následujícím příkazem:

npm init -y

Poté nainstalujeme naše závislosti a uložíme je do souboru package.json:

npm install express socket.io --save

V téže složce vytvoříme soubor index.js pro naši serverovou aplikaci. Obsah souboru by měl být následující:

Vytvoříme instanci express a uložíme ji do proměnné app. Poté vytvoříme server s modulem http. Poté předáme express metodě http.Server(). Express bude sloužit jako obsluha požadavků na náš server. Na oplátku získáme instanci serveru, kterou uložíme do proměnné server.

V dalších dvou řádcích kódu svážeme socket.IO s naším http server:

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

let io = socketIO(server);

Poté nasloucháme události připojení socket.IO a logujeme, jakmile uživatel naváže spojení se serverem. Nakonec spustíme server a nasloucháme na daném portu, v našem případě je to port 3000.
Skutečně spustíme náš server spuštěním následujícího příkazu ve složce server:

node index.js
Následně by se měla zobrazit následující zpráva: „spuštěno na portu: 3000“.

Připojení k Socket.IO

Máme server spuštěný na portu 3000. Nyní je čas podívat se, jak se můžeme k serveru připojit z naší aplikace Angular. K tomu budeme potřebovat nainstalovat klientskou knihovnu Socket.IO. V naší klientské složce spustíme následující příkaz:

npm install socket.io-client --save

Když už jsme v tom, spustíme aplikaci Angular prostřednictvím Angular CLI:

ng serve -o

Nyní máme naši aplikaci spuštěnou. Vidíme, že náš výchozí prohlížeč právě otevřel novou kartu směřující na localhost. Proto jsme pro otevření prohlížeče použili argument -o.

Vytvoření služby pro komunikaci se serverem

Nazvu ji chat.service.ts app.chat.service.ts a umístím ji do složky src. Služba bude zatím co nejjednodušší:

Přidání služby do modulu providers

Také přidáme naši službu ChatService do seznamu providers uvnitř modulu AppModule v souboru app.module.ts:

Vložení služby do naší komponenty

Nakonec budeme službu importovat a používat uvnitř naší komponenty app.component.ts souboru:

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

A službu ChatService injektujeme do našeho konstruktoru:

constructor(chatService: ChatService) { }

Výsledkem je následující soubor:

Pokud vše proběhlo podle očekávání, měli byste po uložení změn vidět v terminálu, kde jste spustili aplikaci node, hlášku „uživatel připojen“:

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

Můžeme tedy říci, že se nám konečně podařilo připojit k našemu Socket IO serveru. Nyní je čas skutečně odeslat nějaká data prostřednictvím událostí Socket IO.

Odeslání zprávy na Socket.IO

Nastal čas vylepšit naši zatím jednoduchou službu ChatService o možnost odeslat zprávu na server:

Pro její fungování musíme použít sendMessage() z naší komponenty AppComponent:

Nakonec poskytneme uživateli jednoduchý textový vstup a tlačítko, aby mohl odeslat zprávu:

Aby to všechno fungovalo, musíme na serveru naslouchat události ‚new-message‘, kterou jsme emitovali z ChatService:

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

Nyní náš index.js vypadá takto:

Pokud si chcete pohrát s kódem, najdete ho v mém repozitáři na GitHubu – rxjs-chat.

Komunikace s ostatními uživateli

Pro to, aby se naše zpráva vysílala ostatním uživatelům, stačí změnit console.log(message) vnitřní volání naší události ‚new-message‘ na io.emit(message):

A co dělá io.emit()? Zjednodušeně řečeno odešle událost všem připojeným k serveru.

Komunikujeme s naším serverem prostřednictvím služby ChatService. Za tímto účelem přidáme do naší služby novou metodu – getMessages. Ta bude vracet observable, které vytvoříme pomocí metody Observable.create(). Pokaždé, když socket obdrží novou zprávu, použijeme observer.next() k jejímu předání pozorovateli.

Poté se přihlásíme k odběru této observable z našeho AppComponent:

Vytvořili jsme nové messages pole, kam budeme ukládat zprávy přijaté ze serveru. Tyto zprávy budeme muset zobrazit v naší šabloně. To je ideální případ použití pro ngFor: