server/ |- src/ |- package.json |- tsconfig.json |- gulpfile.js client/ |- src/ |- package.json |- tsconfig.json |- .angular-cli.json
package.json
file and install the following dependencies: npm install --save express socket.io @types/express @types/socket.io
gulp
and typescript
into the project, all this will be useful to us during the creation and assembly of the finished project: npm install --save-dev typescript gulp gulp-typescript
tsconfig.json
file and put the following into it: { "files": [ "src/*.ts", "src/model/*.ts" ], "compilerOptions": { "target": "es5" } }
export class User { constructor(private name: string) {} } export class Message { constructor(private from: User, private content: string) {} } export class ChatMessage extends Message{ constructor(from: User, content: string) { super(from, content); } }
server/src
directory structure: server/ |- src/ |- model/ |- message.model.ts |- user.model.ts |- index.ts |- server.ts |- package.json |- tsconfig.json |- gulpfile.js
server
directory are index.ts
and chat-server.ts
. The first allows you to create and export the ChatServer
application, while the second contains the express and Socket.IO configurations:index.js
file: import { ChatServer } from './chat-server'; let app = new ChatServer().getApp(); export { app };
chat-server.ts
: import { createServer, Server } from 'http'; import * as express from 'express'; import * as socketIo from 'socket.io'; import { Message } from './model'; export class ChatServer { public static readonly PORT:number = 8080; private app: express.Application; private server: Server; private io: SocketIO.Server; private port: string | number; constructor() { this.createApp(); this.config(); this.createServer(); this.sockets(); this.listen(); } private createApp(): void { this.app = express(); } private createServer(): void { this.server = createServer(this.app); } private config(): void { this.port = process.env.PORT || ChatServer.PORT; } private sockets(): void { this.io = socketIo(this.server); } private listen(): void { this.server.listen(this.port, () => { console.log('Running server on port %s', this.port); }); this.io.on('connect', (socket: any) => { console.log('Connected client on port %s.', this.port); socket.on('message', (m: Message) => { console.log('[server](message): %s', JSON.stringify(m)); this.io.emit('message', m); }); socket.on('disconnect', () => { console.log('Client disconnected'); }); }); } public getApp(): express.Application { return this.app; } }
build
task to the gulpfile.js
file: var gulp = require("gulp"); var ts = require("gulp-typescript"); var tsProject = ts.createProject("tsconfig.json"); gulp.task("build", function () { return tsProject.src() .pipe(tsProject()) .js.pipe(gulp.dest("./dist")); });
dist
directory. To complete the build, you need the following command: gulp build
node dist/index.js
ng new typescript-chat-client --routing --prefix tcc --skip-install
npm install
command, but I prefer to use Yarn in this step: cd typescript-chat-client yarn install
shared
and material
: client/ |- src/ |- app/ |- chat/ |- shared/ |- material/ |- material.module.ts |- shared.module.ts |-app.module.ts
ng generate module shared --module app ng generate module shared/material --module shared
app.module.ts
and shared.module.ts
.express
and socket.io
modules to our client application: npm install express socket.io --save
ng generate module chat --module app
ng generate component chat --module chat
shared
folder. This time - inside the chat
directory: ng generate service chat/shared/services/socket --module chat ng generate class chat/shared/model/user ng generate class chat/shared/model/message
client/ |- src/ |- app/ |- chat/ |- shared/ |- model/ |- user.ts |- message.ts |- services/ |- socket.service.ts |- shared/ |-app.module.ts
socket.services.ts
will look like this: import { Injectable } from '@angular/core'; import { Observable } from 'rxjs/Observable'; import { Observer } from 'rxjs/Observer'; import { Message } from '../model/message'; import { Event } from '../model/event'; import * as socketIo from 'socket.io-client'; const SERVER_URL = 'http://localhost:8080'; @Injectable() export class SocketService { private socket; public initSocket(): void { this.socket = socketIo(SERVER_URL); } public send(message: Message): void { this.socket.emit('message', message); } public onMessage(): Observable<Message> { return new Observable<Message>(observer => { this.socket.on('message', (data: Message) => observer.next(data)); }); } public onEvent(event: Event): Observable<any> { return new Observable<Event>(observer => { this.socket.on(event, () => observer.next()); }); } }
chat.component.ts
file (the code for Material and UI events is omitted here): import { Component, OnInit } from '@angular/core'; import { Action } from './shared/model/action'; import { Event } from './shared/model/event'; import { Message } from './shared/model/message'; import { User } from './shared/model/user'; import { SocketService } from './shared/services/socket.service'; @Component({ selector: 'tcc-chat', templateUrl: './chat.component.html', styleUrls: ['./chat.component.css'] }) export class ChatComponent implements OnInit { action = Action; user: User; messages: Message[] = []; messageContent: string; ioConnection: any; constructor(private socketService: SocketService) { } ngOnInit(): void { this.initIoConnection(); } private initIoConnection(): void { this.socketService.initSocket(); this.ioConnection = this.socketService.onMessage() .subscribe((message: Message) => { this.messages.push(message); }); this.socketService.onEvent(Event.CONNECT) .subscribe(() => { console.log('connected'); }); this.socketService.onEvent(Event.DISCONNECT) .subscribe(() => { console.log('disconnected'); }); } public sendMessage(message: string): void { if (!message) { return; } this.socketService.send({ from: this.user, content: message }); this.messageContent = null; } public sendNotification(params: any, action: Action): void { let message: Message; if (action === Action.JOINED) { message = { from: this.user, action: action } } else if (action === Action.RENAME) { message = { action: action, content: { username: this.user.name, previousUsername: params.previousUsername } }; } this.socketService.send(message); } }
ChatComponent
initialized, the component subscribes to the observed SocketService
objects in order to receive connection-related events or incoming messages.sendMessage
and sendNotification
will send, respectively, messages and notifications through the same service. Notifications are used to notify the system that a new user has joined the chat and to rename the chat participants.Source: https://habr.com/ru/post/347306/
All Articles