Opi rakentamaan reaaliaikainen chat-sovellusliittymä hyödyntäen WebSocketsin tehoa NestJS: n avulla.

NestJS on suosittu kehys palvelinpuolen sovellusten rakentamiseen Node.js: n avulla. WebSockets-tuen ansiosta NestJS soveltuu hyvin reaaliaikaisten chat-sovellusten kehittämiseen.

Joten mitä WebSocketit ovat ja kuinka voit rakentaa reaaliaikaisen chat-sovelluksen NestJS: ssä?

Mitä WebSocketit ovat?

WebSockets on protokolla jatkuvaan, reaaliaikaiseen ja kaksisuuntaiseen viestintään asiakkaan ja palvelimen välillä.

Toisin kuin HTTP: ssä, jossa yhteys suljetaan, kun asiakkaan ja palvelimen välinen pyyntöjakso on suoritettu, WebSocket-yhteys pidetään auki, eikä se sulje, vaikka vastaus on palautettu a pyyntö.

Alla oleva kuva on visualisointi WebSocket-viestinnän toiminnasta palvelimen ja asiakkaan välillä:

Kaksisuuntaisen yhteyden muodostamiseksi asiakas lähettää WebSocket-kättelypyynnön palvelimelle. Pyynnön otsikot sisältävät suojatun WebSocket-avaimen (Sec-WebSocket-Key), ja an Päivitys: WebSocket

instagram viewer
otsikko, joka yhdessä Yhteys: Päivitä otsikko kehottaa palvelinta päivittämään protokollan HTTP: stä WebSocketiin ja pitämään yhteyden auki. Oppiminen aiheesta WebSockets JavaScriptissä auttaa ymmärtämään käsitettä entistä paremmin.

Real-Time Chat APIn luominen NestJS WebSocket -moduulin avulla

Node.js tarjoaa kaksi suurta WebSockets-toteutusta. Ensimmäinen on ws joka toteuttaa paljaat WebSocketit. Ja toinen on socket.io, joka tarjoaa korkeatasoisempia ominaisuuksia.

NestJS: ssä on moduulit molemmille socket.io ja ws. Tässä artikkelissa käytetään socket.io moduuli mallisovelluksen WebSocket-ominaisuuksille.

Tässä projektissa käytetty koodi on saatavilla a GitHub-arkisto. On suositeltavaa kloonata se paikallisesti ymmärtääksesi paremmin hakemistorakennetta ja nähdäksesi kuinka kaikki koodit ovat vuorovaikutuksessa keskenään.

Projektin asetukset ja asennus

Avaa terminaali ja luo uusi NestJS-sovellus käyttämällä pesä uusi komento (esim. pesä uusi chat-sovellus). Komento luo uuden hakemiston, joka sisältää projektitiedostot. Nyt olet valmis aloittamaan kehitysprosessin.

Luo MongoDB-yhteys

Tarvitset tietokannan, jotta voit säilyttää chat-viestit sovelluksessa. Tämä artikkeli käyttää MongoDB-tietokanta NestJS-sovelluksellemme, ja helpoin tapa päästä juoksemaan on perustaa MongoDB-klusterin pilveen ja hanki MongoDB-URL-osoite. Kopioi URL-osoite ja tallenna se nimellä MONGO_URI muuttuja sinun .env tiedosto.

Tarvitset Mongoosea myös myöhemmin, kun teet kyselyitä MongoDB: hen. Asenna se suorittamalla npm asentaa mongoose terminaalissasi.

Vuonna src kansio, luo tiedosto nimeltä mongo.config.ts ja liitä siihen seuraava koodi.

tuonti { rekisteröidä nimellä } alkaen'@nestjs/config';

/**
* Mongo-tietokantayhteyden konfiguraatio
*/

viedäoletuksena registerAs("mongodb", () => {
konst { MONGO_URI } = process.env; // .env-tiedostosta
palata {
uri:`${MONGO_URI}`,
};
});

Sinun projektisi main.ts tiedoston pitäisi näyttää tältä:

tuonti { NestFactory } alkaen'@nestjs/core';
tuonti { AppModule } alkaen'./app.module';
tuonti * kuten cookieParser alkaen'cookie-parser'
tuonti kypärä alkaen'kypärä'
tuonti { Loggeri, ValidationPipe } alkaen"@nestjs/common";
tuonti { setupSwagger } alkaen'./utils/swagger';
tuonti { HttpExceptionFilter } alkaen'./filters/http-exception.filter';

asynktoimintobootstrap() {
konst sovellus = odottaa NestFactory.create (AppModule, { cors: totta });
app.enableCors({
alkuperä: '*',
valtuustiedot: totta
})
app.use (cookieParser())
app.useGlobalPipes(
Uusi ValidationPipe({
sallittujen lista: totta
})
)
konst logger = Uusi Logger("pää")

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

setupSwagger (sovellus)
app.use (kypärä())

odottaa app.listen (AppModule.port)

// lokiasiakirjat
konst baseUrl = AppModule.getBaseUrl (sovellus)
konst url = `http://${baseUrl}:${AppModule.port}`
logger.log(`API-dokumentaatio saatavilla osoitteessa ${url}/docs`);
}
bootstrap();

Chat-moduulin rakentaminen

Aloita reaaliaikaisen chat-ominaisuuden käyttäminen asentamalla NestJS WebSockets -paketit. Tämä voidaan tehdä suorittamalla seuraava komento terminaalissa.

npm asennus @nestjs/websockets @nestjs/platform-socket.io @types/socket.io

Pakettien asennuksen jälkeen sinun on luotava chat-moduuli suorittamalla seuraavat komennot

nest g -moduulin keskustelut
nest g -ohjaimen chatit
nest g -palvelukeskustelut

Kun moduuli on luotu, seuraava vaihe on WebSockets-yhteyden luominen NestJS: ssä. Luo chat.gateway.ts tiedosto sisällä keskustelut kansio, tässä on yhdyskäytävä, joka lähettää ja vastaanottaa viestejä.

Liitä seuraava koodi kohtaan chat.gateway.ts.

tuonti {
MessageBody,
Tilaa viesti,
WebSocketGateway,
WebSocketServer,
} alkaen'@nestjs/websockets';
tuonti { Palvelin } alkaen'socket.io';

@WebSocketGateway()
viedäluokkaaChatGateway{
@WebSocketServer()
palvelin: Palvelin;
// kuuntele send_message -tapahtumia
@Tilaaviesti('Lähetä viesti')
listenForMessages(@MessageBody() viesti: string) {
Tämä.server.sockets.emit('receive_message', viesti);
}
}

Yhdistettyjen käyttäjien todentaminen

Todennus on olennainen osa verkkosovelluksia, eikä se eroa chat-sovelluksesta. Toiminto asiakasyhteyksien todentamiseksi pistorasiaan löytyy kohdasta chats.service.ts kuten tässä näkyy:

@Injektoitava()
viedäluokkaaChatsService{
rakentaja(yksityinen authService: AuthService) {}

asynk getUserFromSocket (socket: Socket) {
antaa auth_token = socket.handshake.headers.authorization;
// hanki itse merkki ilman "Bearer"
auth_token = auth_token.split(' ')[1];

konst käyttäjä = Tämä.authService.getUserFromAuthenticationToken(
auth_token
);

jos (!käyttäjä) {
heittääUusi WsException("Virheelliset tunnistetiedot.");
}
palata käyttäjä;
}
}

The getUserFromSocket menetelmän käyttöä getUserFromAuthenticationToken saadaksesi tällä hetkellä kirjautuneen käyttäjän JWT-tunnuksesta purkamalla Bearer-tunnuksen. The getUserFromAuthenticationToken toiminto on toteutettu auth.service.ts tiedosto kuten tässä näkyy:

julkinen asynk getUserFromAuthenticationToken (tunnus: merkkijono) {
konst hyötykuorma: JwtPayload = Tämä.jwtService.verify (token, {
salaisuus: Tämä.configService.get('JWT_ACCESS_TOKEN_SECRET'),
});

konst userId = payload.sub

jos (käyttäjätunnus) {
palataTämä.usersService.findById (userId);
}
}

Nykyinen liitäntä välitetään parametrina getUserFromSocket kun käsittele Connection menetelmä ChatGateway toteuttaa OnGatewayConnection käyttöliittymä. Tämä mahdollistaa viestien ja tiedon vastaanottamisen tällä hetkellä yhteydessä olevasta käyttäjästä.

Alla oleva koodi osoittaa tämän:

// chat.gateway.ts
@WebSocketGateway()
viedäluokkaaChatGatewaytoteuttaaOnGatewayConnection{
@WebSocketServer()
palvelin: Palvelin;

rakentaja(yksityinen chatService: ChatsService) {}

asynk handleConnection (socket: Socket) {
odottaaTämä.chatsService.getUserFromSocket (socket)
}

@Tilaaviesti('Lähetä viesti')
asynk listenForMessages(@MessageBody() viesti: string, @ConnectedSocket() socket: Socket) {

konst käyttäjä = odottaaTämä.chatsService.getUserFromSocket (socket)
Tämä.server.sockets.emit('receive_message', {
viesti,
käyttäjä
});
}
}

Voit viitata yllä oleviin todennusjärjestelmään liittyviin tiedostoihin GitHub-arkisto nähdäksesi täydelliset koodit (mukaan lukien tuonti), jotta ymmärrät paremmin toteutuksen.

Pysyvät keskustelut tietokantaan

Jotta käyttäjät voivat nähdä viestihistoriansa, tarvitset skeeman viestien tallentamista varten. Luo uusi tiedosto nimeltä message.schema.ts ja liitä alla oleva koodi siihen (muista tuoda käyttäjäskeema tai tarkista yksi arkisto).

tuonti { Käyttäjä } alkaen'./../users/schemas/user.schema';
tuonti { Prop, Schema, SchemaFactory } alkaen"@nestjs/mangoose";
tuonti mangoose, { asiakirja } alkaen"mungo";

viedä type MessageDocument = Viesti & asiakirja;

@Schema({
toJSON: {
saajat: totta,
Virtuaalit: totta,
},
aikaleimat: totta,
})
viedäluokkaaViesti{
@Prop({ edellytetään: totta, ainutlaatuinen: totta })
viesti: merkkijono

@Prop({ tyyppi: mangoose. Kaavio. Tyypit. ObjectId, viite: "Käyttäjä" })
käyttäjä: Käyttäjä
}

konst MessageSchema = SchemaFactory.createForClass (viesti)

viedä { MessageSchema };

Alla on toteutettu palvelu, jolla luodaan uusi viesti ja saadaan kaikki viestit perille chats.service.ts.

tuonti { Viesti, Viestiasiakirja } alkaen'./message.schema'; 
tuonti { Pistorasia } alkaen'socket.io';
tuonti { AuthService } alkaen'./../auth/auth.service';
tuonti { Injektoitava } alkaen"@nestjs/common";
tuonti { WsException } alkaen'@nestjs/websockets';
tuonti { InjectModel } alkaen"@nestjs/mangoose";
tuonti { Malli } alkaen'mungo';
tuonti { ViestiDto } alkaen'./dto/message.dto';

@Injektoitava()
viedäluokkaaChatsService{
rakentaja(yksityinen authService: AuthService, @InjectModel (Message.name) yksityinen viestiMalli: Malli) {}
...
asynk createMessage (viesti: ViestiDto, käyttäjätunnus: merkkijono) {
konst uusi viesti = UusiTämä.messageModel({...viesti, käyttäjätunnus})
odottaa uusiviesti.tallenna
palata uusi viesti
}
asynk getAllMessages() {
palataTämä.messageModel.find().populate('käyttäjä')
}
}

The ViestiDto toteutetaan kohdassa a message.dto.ts tiedosto tiedostoon dto -kansiossa keskustelut hakemistosta. Löydät sen myös arkistosta.

Sinun on lisättävä viesti malli ja skeema tuontiluetteloon chats.module.ts.

tuonti { Viesti, MessageSchema } alkaen'./message.schema';
tuonti { Moduuli } alkaen"@nestjs/common";
tuonti { ChatGateway } alkaen'./chats.gateway';
tuonti { ChatService } alkaen'./chats.service';
tuonti { MongooseModule } alkaen"@nestjs/mangoose";

@Moduuli({
tuonti: [MongooseModule.forFeature([
{ nimi: Viesti.nimi, kaava: MessageSchema }
])],
ohjaimet: [],
palveluntarjoajat: [ChatsService, ChatGateway]
})
viedäluokkaaChatsModule{}

Lopuksi, get_all_messages tapahtumien käsittelijä on lisätty ChatGateway luokka sisään chat.gateway.ts kuten seuraavasta koodista näkyy:

// tuonti...

@WebSocketGateway()
viedäluokkaaChatGatewaytoteuttaaOnGatewayConnection{
...

@Tilaaviesti("get_all_messages")
asynk getAllMessages(@ConnectedSocket() socket: Socket) {

odottaaTämä.chatsService.getUserFromSocket (socket)
konst viestit = odottaaTämä.chatsService.getAllMessages()

Tämä.server.sockets.emit('receive_message', viestit);

palata viestejä
}
}

Kun yhdistetty asiakas (käyttäjä) lähettää get_all_messages tapahtumasta, kaikki heidän viestinsä haetaan ja milloin ne lähetetään Lähetä viesti, viesti luodaan ja tallennetaan tietokantaan ja lähetetään sitten kaikille muille yhdistetyille asiakkaille.

Kun olet suorittanut kaikki yllä olevat vaiheet, voit aloittaa sovelluksesi käyttämällä npm ajon aloitus: devja testaa sitä WebSocket-asiakkaalla, kuten Postman.

Reaaliaikaisten sovellusten rakentaminen NestJS: n avulla

Vaikka reaaliaikaisten järjestelmien rakentamiseen on muitakin tekniikoita, WebSocketit ovat erittäin suosittuja ja helppokäyttöisiä monissa tapauksissa, ja ne ovat paras vaihtoehto chat-sovelluksiin.

Reaaliaikaiset sovellukset eivät rajoitu vain chat-sovelluksiin, vaan muita esimerkkejä ovat videon suoratoisto tai soittosovelluksia ja live-sääsovelluksia, ja NestJS tarjoaa loistavat työkalut reaaliaikaiseen rakentamiseen sovelluksia.