Chat-Anwendung mit Angular und Socket.IO

Einführung

Wir werden RxJS, Angular, express (Node.js) & Socket.IO verwenden, um eine Chat-Anwendung zu erstellen. Wir werden sehen, wie nützlich RxJS in diesem Szenario sein kann. Um die Dinge reibungslos und einfach zu gestalten, werden wir Angular CLI verwenden, um eine grundlegende Client-Struktur zu generieren und uns eine Boilerplate für die einfachste funktionierende Angular-Anwendung zu erstellen. Auf dem Back-End werden wir Node.js mit Express und Socket.IO verwenden. Der Grund dafür ist, dass Socket.IO sehr einfach einzurichten und zu verwenden ist. Außerdem bietet es sowohl server- als auch clientseitige Bibliotheken. Socket.IO verwendet in erster Linie das WebSocket-Protokoll, um bidirektionale Kommunikation in Echtzeit zu ermöglichen.

Wenn Sie direkt zu dem Teil springen wollen, in dem wir RxJS zur Verarbeitung der Chat-Nachrichten verwenden, klicken Sie hier.

Lassen Sie uns beginnen!

Socket.IO Server Setup

Wenn Sie Angular CLI nicht installiert haben, können Sie es ganz einfach installieren:

npm i -g @angular/cli

Ordnerstruktur einrichten

Um die Dinge sauber zu halten, werden wir einen neuen rxjs-chat Ordner für unser kleines Projekt erstellen. Er soll als Stammordner für Angular- und Socket.IO-Apps dienen.

Lassen Sie uns eine einfache Angular-App mit Angular CLI erstellen. Starten Sie in unserem Projektordner Ihr bevorzugtes Terminal und führen Sie den folgenden Befehl aus:

ng new rxjs-chat

Gönnen Sie dem Ganzen ein wenig Zeit. Nachdem die Grundstruktur erstellt und die npm-Pakete installiert wurden, benennen wir den neu erstellten Angular-Projektordner in Client um. Danach erstellen wir im gleichen Stammordner den Ordner server für unseren Socket.IO-Server. Jetzt haben wir zwei Ordner in unserem rxjs-chat Ordner:

  • client – Angular client app
  • server – bald Node’s Socket.IO server
Installation von lokalen Paketen

Im server Ordner werden wir package.json-Datei, indem wir den folgenden Befehl ausführen:

npm init -y

Danach installieren wir unsere Abhängigkeiten und speichern sie in package.json:

npm install express socket.io --save

Im gleichen Ordner erstellen wir die Datei index.js für unsere Server-App. Der Inhalt der Datei sollte wie folgt aussehen:

Wir erstellen eine Instanz von express und speichern sie in der Variablen app. Danach erstellen wir einen Server mit dem Modul http. Dann übergeben wir express an die Methode http.Server(). Express wird als Handler für Anfragen an unseren Server dienen. Im Gegenzug erhalten wir die Instanz des Servers, die wir in der server-Variable speichern.

In den nächsten beiden Codezeilen binden wir socket.IO mit unserem http server:

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

let io = socketIO(server);

Danach lauschen wir auf das Verbindungsereignis von socket.IO und protokollieren, sobald ein Benutzer eine Verbindung mit dem Server hergestellt hat. Schließlich starten wir den Server und lauschen auf dem angegebenen Port, in unserem Fall ist es Port 3000.
Lassen Sie uns unseren Server tatsächlich starten, indem Sie das Folgende im Server-Ordner ausführen:
node index.js
Anschließend sollten Sie die folgende Meldung erhalten: „started on port: 3000“.

Verbinden mit Socket.IO

Wir haben einen Server, der an Port 3000 läuft. Jetzt ist es an der Zeit zu sehen, wie wir uns von unserer Angular-App aus mit dem Server verbinden können. Dazu müssen wir die Socket.IO-Client-Bibliothek installieren. Wir führen den folgenden Befehl in unserem Client-Ordner aus:

npm install socket.io-client --save

Während wir dabei sind, können wir die Angular-App über Angular CLI ausführen:

ng serve -o

Jetzt läuft unsere App. Wir können sehen, dass unser Standardbrowser gerade einen neuen Tab geöffnet hat, der auf localhost zeigt. Deshalb haben wir das Argument -o verwendet, um den Browser zu öffnen.

Erstellen eines Dienstes für die Kommunikation mit dem Server

Ich werde ihn chat.service.ts app.chat.service.ts nennen und ihn im Ordner src platzieren. Der Dienst wird so einfach wie möglich sein:

Den Dienst zu den Modulprovidern hinzufügen

Auch fügen wir unseren ChatService zur Providerliste innerhalb des AppModuls in der Datei app.module.ts hinzu:

Den Dienst in unsere Komponente einfügen

Schließlich importieren und verwenden wir den Dienst innerhalb unserer app.component.ts-Datei importieren und verwenden:

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

Und wir werden den ChatService in unseren Konstruktor injizieren:

constructor(chatService: ChatService) { }

Als Ergebnis haben wir die folgende Datei:

Wenn alles wie erwartet gelaufen ist, sollten Sie nach dem Speichern der Änderungen die Meldung ‚user connected‘ in dem Terminal sehen, in dem Sie node app gestartet haben:

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

Damit können wir sagen, dass wir es endlich geschafft haben, uns mit unserem Socket IO Server zu verbinden. Nun ist es an der Zeit, einige Daten über Socket IO-Ereignisse zu senden.

Senden einer Nachricht an Socket.IO

Zeit, unseren bisher einfachen ChatService mit einer Option zum Senden einer Nachricht an den Server zu erweitern:

Damit das funktioniert, müssen wir sendMessage() von unserer AppComponent verwenden:

Schließlich wollen wir dem Benutzer eine einfache Texteingabe und eine Schaltfläche anbieten, damit er eine Nachricht senden kann:

Damit das alles funktioniert, müssen wir auf dem Server auf das ’new-message‘-Ereignis lauschen, das wir vom ChatService emittiert haben:

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

Nun sieht unser index.js wie folgt aus:

Wenn du mit dem Code herumspielen möchtest, findest du ihn in meinem GitHub Repo – rxjs-chat.

Kommunikation mit anderen Nutzern

Damit unsere Nachricht an andere Nutzer gesendet wird, müssen wir nur den console.log(message) innerhalb unseres ’new-message‘-Ereignis-Callbacks auf io.emit(message) ändern:

Und was macht io.emit()? In einfachen Worten: Es sendet ein Ereignis an alle, die mit dem Server verbunden sind.

Lassen Sie uns mit unserem Server über ChatService kommunizieren. Zu diesem Zweck fügen wir eine neue Methode zu unserem Dienst hinzu – getMessages. Sie wird ein Observable zurückgeben, das wir mit der Methode Observable.create() erstellen werden. Jedes Mal, wenn Socket eine neue Nachricht empfängt, werden wir observer.next() verwenden, um sie an Observer weiterzuleiten.

Danach abonnieren wir diese Observable von unserer AppComponent:

Wir haben ein neues messages Array erstellt, in dem wir die vom Server empfangenen Nachrichten speichern werden. Wir werden diese Nachrichten in unserem Template anzeigen müssen. Das ist der perfekte Anwendungsfall für ngFor: