Chattprogram med Angular och Socket.IO

Introduktion

Vi kommer att använda RxJS, Angular, express (Node.js) & Socket.IO för att skapa ett chattprogram. Vi kommer att få se hur användbar RxJS kan vara i detta scenario. För att göra det hela smidigt och enkelt kommer vi att använda Angular CLI för att generera en grundläggande klientstruktur och ge oss en boilerplate för den enklaste fungerande Angular-applikationen. På baksidan kommer vi att använda Node.js med express och Socket.IO. Anledningen till detta är att Socket.IO är mycket lätt att sätta upp och arbeta med. Dessutom tillhandahåller det bibliotek på både server- och klientsidan. Socket.IO använder främst WebSocket-protokollet för att möjliggöra dubbelriktad kommunikation i realtid.

Om du vill hoppa direkt till den del där vi använder RxJS för att hantera chattmeddelanden klickar du här.

Vi kan börja!

Socket.IO server setup

Om du inte har Angular CLI installerat kan du installera det ganska enkelt:

npm i -g @angular/cli

Sätt upp mappstruktur

För att hålla saker och ting rena kommer vi att skapa en ny rxjs-chat-mapp för vårt lilla projekt. Den ska fungera som rotmapp för Angular- och Socket.IO-appar.

Låt oss skapa en grundläggande Angular-app med hjälp av Angular CLI. I vår projektmapp startar du din favoritterminal och kör följande kommando:

ng new rxjs-chat

Giv det lite tid. När den är klar med att skapa den grundläggande strukturen och installera npm-paket kommer vi att byta namn på den nyskapade Angular-projektmappen till client. Därefter skapar vi i samma rotmapp en mapp server för vår Socket.IO-server. Nu har vi två mappar i vår rxjs-chat-mapp:

  • klient – Angular-klientapp
  • server – snart Node Socket.IO-server
Installation av lokala paket

I mappen server kommer vi att generera paket.json-filen genom att köra följande kommando:

npm init -y

Därefter installerar vi våra beroenden och sparar dem i package.json:

npm install express socket.io --save

I samma mapp skapar vi index.js-filen för vår serverapp. Innehållet i filen ska vara följande:

Vi skapar en instans av express och lagrar den i variabeln app. Därefter skapar vi en server med modulen http. Sedan skickar vi express till http.Server()-metoden. Express kommer att fungera som handläggare för förfrågningar till vår server. I gengäld får vi instansen av servern som vi lagrar i server-variabeln.

I nästa två rader kod binder vi socket.IO med vår http server:

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

let io = socketIO(server);

Efter det lyssnar vi på anslutningshändelsen av socket.IO och vi loggar så fort en användare har upprättat en anslutning med servern. Slutligen startar vi servern och lyssnar på en given port, i vårt fall är det port 3000.

Låt oss faktiskt starta vår server genom att köra följande i servermappen:
node index.js
Därefter bör du få följande meddelande: ”started on port: 3000”.

Anslutning till Socket.IO

Vi har en server som körs på port 3000. Nu är det dags att se hur vi kan ansluta till servern från vår Angular-app. För detta behöver vi installera klientbiblioteket Socket.IO. Vi kör följande kommando i vår klientmapp:

npm install socket.io-client --save

När vi ändå är igång kan vi köra Angular-appen via Angular CLI:

ng serve -o

Nu har vi vår app igång. Vi kan se att vår standardwebbläsare just öppnat en ny flik som pekar på localhost. Det är därför vi använde -oargumentet för att öppna webbläsaren.

Skapa tjänst för kommunikation med servern

Jag kommer att döpa den till chat.service.ts app.chat.service.ts och placera den i src-mappen. Tjänsten kommer att vara så enkel som möjligt för tillfället:

Tillägga tjänsten till modulens providers

Också, låt oss lägga till vår ChatService till providers-listan inne i AppModule i app.module.ts-filen:

Injicera tjänsten i vår komponent

Slutligt kommer vi att importera och använda tjänsten inne i vår app.component.ts-fil:

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

Och vi kommer att injicera ChatService i vår konstruktör:

constructor(chatService: ChatService) { }

Som ett resultat har vi följande fil:

Om allt gick som förväntat efter att ha sparat ändringarna bör du se meddelandet ”user connected” i terminalen där du startade node app:

$ node index.js
started on port: 3000

Därmed kan vi säga att vi äntligen lyckades ansluta till vår Socket IO-server. Nu är det dags att faktiskt skicka några data via Socket IO-händelser.

Sända ett meddelande till Socket.IO

Det är dags att förbättra vår hittills enkla ChatService med ett alternativ för att skicka ett meddelande till servern:

För att detta ska fungera måste vi använda sendMessage() från vår AppComponent:

Finally, lets provide user with a simple text input and a button so he can send a message:

För att allt detta ska fungera måste vi lyssna på servern på händelsen ”new-message” som vi skickade ut från ChatService:

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

Nu kommer vårt index.js ser ut så här:

Om du vill leka med koden kan du hitta den på min GitHub-repo – rxjs-chat.

Kommunikation med andra användare

För att vårt meddelande ska kunna sändas ut till andra användare behöver vi bara ändra console.log(message) inne i vår ”new-message”-händelse callback till io.emit(message):

Och vad gör io.emit()? Med enkla ord skickar den en händelse till alla som är anslutna till servern.

Låt oss kommunicera med vår server via ChatService. Vi kommer att lägga till en ny metod till vår tjänst för detta ändamål – getMessages. Den kommer att returnera en Observable som vi kommer att skapa med Observable.create()-metoden. Varje gång socket tar emot ett nytt meddelande kommer vi att använda observer.next() för att vidarebefordra det till observatörer.

Efter det prenumererar vi på denna Observable från vår AppComponent:

Vi har skapat ett nytt messages array där vi kommer att lagra meddelanden som tas emot från servern. Vi kommer att behöva visa dessa meddelanden i vår mall. Det är ett perfekt användningsområde för ngFor: