Uzziniet, kā izveidot reāllaika tērzēšanas API, izmantojot WebSockets iespējas, izmantojot NestJS.

NestJS ir populārs ietvars servera puses lietojumprogrammu izveidei, izmantojot Node.js. Ar WebSockets atbalstu NestJS ir labi piemērots reāllaika tērzēšanas lietojumprogrammu izstrādei.

Tātad, kas ir WebSockets un kā jūs varat izveidot reāllaika tērzēšanas lietotni NestJS?

Kas ir WebSockets?

WebSockets ir protokols pastāvīgai, reāllaika un divvirzienu komunikācijai starp klientu un serveri.

Atšķirībā no HTTP, kur savienojums tiek aizvērts, kad tiek pabeigts pieprasījuma cikls starp klientu un serveri, WebSocket savienojums tiek turēts atvērts un netiek aizvērts pat pēc tam, kad ir saņemta atbilde uz a pieprasījumu.

Tālāk esošajā attēlā ir vizualizēts, kā darbojas WebSocket komunikācija starp serveri un klientu:

Lai izveidotu divvirzienu saziņu, klients serverim nosūta WebSocket rokasspiediena pieprasījumu. Pieprasījuma galvenes satur drošu WebSocket atslēgu (Sec-WebSocket-Key), un an Jauninājums: WebSocket

galvene, kas kopā ar Savienojums: jauninājums galvene liek serverim jaunināt protokolu no HTTP uz WebSocket un saglabāt savienojumu atvērtu. Mācīšanās par WebSockets JavaScript palīdz vēl labāk izprast jēdzienu.

Reāllaika tērzēšanas API izveide, izmantojot NestJS WebSocket moduli

Node.js nodrošina divas galvenās WebSockets implementācijas. Pirmais ir ws kas ievieš tukšas WebSockets. Un otrais ir socket.io, kas nodrošina vairāk augsta līmeņa funkciju.

NestJS ir moduļi abiem socket.io un ws. Šajā rakstā tiek izmantots socket.io modulis parauga lietojumprogrammas WebSocket funkcijām.

Šajā projektā izmantotais kods ir pieejams a GitHub repozitorijs. Ieteicams to klonēt lokāli, lai labāk izprastu direktoriju struktūru un redzētu, kā visi kodi mijiedarbojas viens ar otru.

Projekta iestatīšana un uzstādīšana

Atveriet savu termināli un ģenerējiet jaunu NestJS lietotni, izmantojot ligzda jauna komanda (piem. ligzdot jaunu tērzēšanas lietotni). Komanda ģenerē jaunu direktoriju, kurā ir projekta faili. Tagad esat gatavs sākt izstrādes procesu.

Iestatiet MongoDB savienojumu

Lai saglabātu tērzēšanas ziņojumus lietojumprogrammā, ir nepieciešama datu bāze. Šis raksts izmanto MongoDB datu bāze mūsu NestJS lietojumprogrammai, un vienkāršākais veids, kā sākt skriet, ir iestatiet MongoDB klasteru mākonī un iegūstiet savu MongoDB URL. Nokopējiet URL un saglabājiet to kā MONGO_URI mainīgs jūsu .env failu.

Mongoose jums būs nepieciešams arī vēlāk, kad veicat vaicājumus MongoDB. Instalējiet to, palaižot npm instalēt mongoose savā terminālī.

Iekš src mapi, izveidojiet failu ar nosaukumu mongo.config.ts un ielīmējiet tajā šādu kodu.

imports { registerAs } no"@nestjs/config";

/**
* Mongo datu bāzes savienojuma konfigurācija
*/

eksportētnoklusējuma registerAs("mongodb", () => {
konst { MONGO_URI } = process.env; // no .env faila
atgriezties {
uri:`${MONGO_URI}`,
};
});

Jūsu projekts galvenais.ts failam vajadzētu izskatīties šādi:

imports { NestFactory } no'@nestjs/core';
imports { AppModule } no'./app.module';
imports * cookieParser no'cookie-parser'
imports ķivere no"ķivere"
imports { Logger, ValidationPipe } no"@nestjs/common";
imports { setupSwagger } no'./utils/swagger';
imports { HttpExceptionFilter } no'./filters/http-exception.filter';

asinhronsfunkcijubootstrap() {
konst lietotne = gaidīt NestFactory.create (AppModule, { cors: taisnība });
app.enableCors({
izcelsme: '*',
akreditācijas dati: taisnība
})
app.use (cookieParser())
app.useGlobalPipes(
jauns ValidationPipe({
baltais saraksts: taisnība
})
)
konst mežizstrādātājs = jauns Reģistrētājs("Galvenais")

app.setGlobalPrefix('api/v1')
app.useGlobalFilters(jauns HttpExceptionFilter());

setupSwagger (lietotne)
app.use (ķivere())

gaidīt app.listen (AppModule.port)

// žurnāla dokumenti
konst baseUrl = AppModule.getBaseUrl (lietotne)
konst url = `http://${baseUrl}:${AppModule.port}`
logger.log(`API dokumentācija pieejama vietnē ${url}/docs`);
}
bootstrap ();

Tērzēšanas moduļa izveide

Lai sāktu darbu ar reāllaika tērzēšanas funkciju, pirmais solis ir instalēt NestJS WebSockets pakotnes. To var izdarīt, terminālī izpildot šādu komandu.

npm instalēt @nestjs/websockets @nestjs/platform-socket.io @types/socket.io

Pēc pakotņu instalēšanas jums ir jāģenerē tērzēšanas modulis, izpildot šādas komandas

nest g moduļa tērzēšana
nest g kontroliera tērzēšana
nest g pakalpojumu tērzēšanas

Kad modulis ir ģenerēts, nākamais solis ir izveidot WebSockets savienojumu NestJS. Izveidot a chat.gateway.ts failu iekšpusē tērzēšana mapē, šeit ir ieviesta vārteja, kas nosūta un saņem ziņojumus.

Ielīmējiet tālāk norādīto kodu chat.gateway.ts.

imports {
Message Body,
Abonēt ziņojumu,
WebSocketGateway,
WebSocketServer,
} no'@nestjs/websockets';
imports { Serveris } no'socket.io';

@WebSocketGateway()
eksportētklasēChatGateway{
@WebSocketServer()
serveris: serveris;
// klausieties send_message notikumus
@SubscribeMessage('sūtīt ziņu')
listenForMessages(@MessageBody() message: string) {
šis.server.sockets.emit('receive_message', ziņa);
}
}

Savienoto lietotāju autentifikācija

Autentifikācija ir būtiska tīmekļa lietojumprogrammu sastāvdaļa, un tā neatšķiras arī tērzēšanas lietojumprogrammās. Funkcija, lai autentificētu klienta savienojumus ar ligzdu, ir atrodama chats.service.ts kā parādīts šeit:

@Injicējams()
eksportētklasēTērzēšanas pakalpojums{
konstruktors(privāts authService: AuthService) {}

asinhrons getUserFromSocket (ligzda: Socket) {
ļaut auth_token = socket.handshake.headers.authorization;
// iegūt pašu marķieri bez "nesēja"
auth_token = auth_token.split(' ')[1];

konst lietotājs = šis.authService.getUserFromAuthenticationToken(
auth_token
);

ja (!lietotājs) {
mestjauns WsException("Nederīgi akreditācijas dati.");
}
atgriezties lietotājs;
}
}

The getUserFromSocket metodes lietojumi getUserFromAuthenticationToken lai iegūtu pašlaik pieteikušos lietotāju no JWT marķiera, izvelkot nesēja marķieri. The getUserFromAuthenticationToken funkcija ir ieviesta auth.service.ts failu, kā parādīts šeit:

publiski asinhrons getUserFromAuthenticationToken (token: virkne) {
konst lietderīgā slodze: JwtPayload = šis.jwtService.verify (token, {
noslēpums: šis.configService.get("JWT_ACCESS_TOKEN_SECRET"),
});

konst userId = payload.sub

ja (Lietotāja ID) {
atgrieztiesšis.usersService.findById (userId);
}
}

Pašreizējā ligzda tiek nodota kā parametrs getUserFromSocket kad rokturisSavienojums metode ChatGateway īsteno OnGatewayConnection saskarne. Tas dod iespēju saņemt ziņas un informāciju par pašlaik pievienoto lietotāju.

Tālāk redzamais kods to parāda:

// chat.gateway.ts
@WebSocketGateway()
eksportētklasēChatGatewayīstenoOnGatewayConnection{
@WebSocketServer()
serveris: serveris;

konstruktors(privāts chatsService: ChatsService) {}

asinhrons handConnection (ligzda: Socket) {
gaidītšis.chatsService.getUserFromSocket (ligzda)
}

@SubscribeMessage('sūtīt ziņu')
asinhrons listenForMessages(@MessageBody() ziņojums: virkne, @ConnectedSocket() ligzda: Socket) {

konst lietotājs = gaidītšis.chatsService.getUserFromSocket (ligzda)
šis.server.sockets.emit('receive_message', {
ziņa,
lietotājs
});
}
}

Jūs varat atsaukties uz failiem, kas ir iesaistīti autentifikācijas sistēmā iepriekš GitHub repozitorijs lai redzētu pilnus kodus (ieskaitot importu), lai labāk izprastu ieviešanu.

Pastāvīga tērzēšana datu bāzē

Lai lietotāji varētu redzēt savu ziņojumapmaiņas vēsturi, jums ir nepieciešama ziņojumu glabāšanas shēma. Izveidojiet jaunu failu ar nosaukumu message.schema.ts un ielīmējiet tajā tālāk norādīto kodu (neaizmirstiet importēt savu lietotāja shēma vai pārbaudiet repozitoriju.

imports {Lietotājs} no'./../users/schemas/user.schema';
imports { Prop, Schema, SchemaFactory } no"@nestjs/mangoose";
imports mangusts, { dokuments } no"mangusts";

eksportēt ierakstiet MessageDocument = Ziņojums un dokuments;

@Schema({
uz JSON: {
ieguvēji: taisnība,
virtuālie: taisnība,
},
laikspiedoli: taisnība,
})
eksportētklasēZiņojums{
@Prop({ nepieciešams: taisnība, unikāla: taisnība })
ziņojums: virkne

@Prop({ veids: mangusts. Shēma. Veidi. Objekta ID, ref: 'Lietotājs' })
lietotājs: lietotājs
}

konst MessageSchema = SchemaFactory.createForClass (Ziņojums)

eksportēt { MessageSchema };

Tālāk ir sniegta pakalpojumu ieviešana, lai izveidotu jaunu ziņojumu un saņemtu visus ziņojumus chats.service.ts.

imports { Message, MessageDocument } no'./message.schema'; 
imports { Socket } no'socket.io';
imports { AuthService } no"./../auth/auth.service";
imports {Injicējams} no"@nestjs/common";
imports { WsException } no'@nestjs/websockets';
imports { InjectModel } no"@nestjs/mangoose";
imports { Modelis } no'mangusts';
imports { MessageDto } no'./dto/message.dto';

@Injicējams()
eksportētklasēTērzēšanas pakalpojums{
konstruktors(privāts authService: AuthService, @InjectModel (Message.name) privātais ziņojumsModelis: modelis) {}
...
asinhrons createMessage (ziņojums: MessageDto, Lietotāja ID: virkne) {
konst jauns ziņojums = jaunsšis.messageModel({...ziņojums, lietotāja ID})
gaidīt jaunsZiņojums.saglabāt
atgriezties jauns ziņojums
}
asinhrons getAllMessages() {
atgrieztiesšis.messageModel.find().populate('lietotājs')
}
}

The ZiņaDto tiek īstenots a message.dto.ts failu mapē dto mapē tērzēšana direktoriju. To var atrast arī repozitorijā.

Jums jāpievieno ziņa modeli un shēmu uz importēto preču sarakstu chats.module.ts.

imports { Message, MessageSchema } no'./message.schema';
imports { Modulis } no"@nestjs/common";
imports { ChatGateway } no'./chats.gateway';
imports { ChatsService } no'./chats.service';
imports { MongooseModule } no"@nestjs/mangoose";

@Module({
imports: [MongooseModule.forFeature([
{ nosaukums: Message.name, shēma: MessageSchema }
])],
kontrolieri: [],
pakalpojumu sniedzēji: [ChatsService, ChatGateway]
})
eksportētklasēChatsModule{}

Visbeidzot, get_all_messages notikumu apstrādātājs ir pievienots ChatGateway klasē iekšā chat.gateway.ts kā redzams šajā kodā:

// imports...

@WebSocketGateway()
eksportētklasēChatGatewayīstenoOnGatewayConnection{
...

@SubscribeMessage("get_all_messages")
asinhrons getAllMessages(@ConnectedSocket() ligzda: Socket) {

gaidītšis.chatsService.getUserFromSocket (ligzda)
konst ziņas = gaidītšis.chatsService.getAllMessages()

šis.server.sockets.emit('receive_message', ziņas);

atgriezties ziņas
}
}

Kad pievienots klients (lietotājs) izstaro get_all_messages notikumu, visi viņu ziņojumi tiks izgūti un kad tie tiks izsūtīti sūtīt ziņu, ziņojums tiek izveidots un saglabāts datu bāzē un pēc tam nosūtīts visiem pārējiem pievienotajiem klientiem.

Kad esat pabeidzis visas iepriekš minētās darbības, varat sākt lietojumprogrammu, izmantojot npm palaišanas sākums: devun pārbaudiet to ar WebSocket klientu, piemēram, Postman.

Reāllaika lietojumprogrammu izveide, izmantojot NestJS

Lai gan ir arī citas tehnoloģijas reāllaika sistēmu izveidei, WebSockets ir ļoti populārs un daudzos gadījumos viegli ieviešams, un tas ir labākais risinājums tērzēšanas lietojumprogrammām.

Reāllaika lietojumprogrammas neaprobežojas tikai ar tērzēšanas lietojumprogrammām, citi piemēri ietver video straumēšanu vai zvanīšanas lietojumprogrammas un reāllaika laikapstākļu lietojumprogrammas, un NestJS nodrošina lieliskus rīkus reāllaika izveidei lietotnes.