Gerbang WebSocket dengan Penyesuai Socket.IO
Laksanakan pengendali @WebSocketGateway, bilik dan cangkuk kitar hayat untuk komunikasi langsung
Gerbang WebSocket dengan Penyesuai Socket.IO ialah pelajaran API Bahagian Belakang Perusahaan NestJS percuma di CoddyKit. Ini ialah pelajaran 1 daripada 4. Anda boleh membaca keseluruhan pelajaran di bawah secara percuma — kemudian berlatih secara praktikal dalam pelayar menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran API Bahagian Belakang Perusahaan NestJS, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus API Bahagian Belakang Perusahaan NestJS merangkumi sejumlah 4 pelajaran.
Sebab Gateway Wujud
REST mengendalikan permintaan/respons, tetapi ciri masa nyata (sembang, kehadiran, papan pemuka langsung) memerlukan saluran berterusan dan dua hala. NestJS membungkusnya dengan Gateway WebSocket.
- Gateway ialah penyedia yang dihiasi dengan
@WebSocketGateway(). - Secara lalai, Nest menggunakan penyesuai platform Socket.IO (
@nestjs/platform-socket.io). - Gateway ialah kelas Nest biasa: ia menyokong suntikan kebergantungan, pengawal keselamatan, paip dan pencegat sama seperti pengawal.
Pasang kebergantungan dengan npm i @nestjs/websockets @nestjs/platform-socket.io socket.io.
Mengisytiharkan Gateway
Hiasi satu kelas dengan @WebSocketGateway() dan daftarkannya sebagai penyedia dalam modul. Anda boleh menghantar port dan pilihan seperti namespace serta konfigurasi CORS.
@SubscribeMessage('event')mengikat pengendali kepada event Socket.IO masuk.- Nilai pulangan (atau
WsResponse) dihantar semula kepada klien yang memanggil.
Dalam contoh di bawah, klien yang menghantar ping menerima balasan pong.
import { WebSocketGateway, SubscribeMessage, MessageBody } from '@nestjs/websockets';
@WebSocketGateway({ namespace: '/chat', cors: { origin: '*' } })
export class ChatGateway {
@SubscribeMessage('ping')
handlePing(@MessageBody() data: string): { event: string; data: string } {
return { event: 'pong', data: `received: ${data}` };
}
}Mengakses Tika Server
Untuk menyiarkan kepada banyak klien, anda memerlukan Server Socket.IO yang mendasarinya. Suntikkannya dengan penghias sifat @WebSocketServer().
server.emit('event', payload)menghantar kepada setiap klien yang bersambung dalam ruang nama tersebut.- Ini menjadi asas bagi ciri penyiaran seperti pengumuman global.
import { WebSocketGateway, WebSocketServer, SubscribeMessage, MessageBody } from '@nestjs/websockets';
import { Server } from 'socket.io';
@WebSocketGateway({ namespace: '/chat' })
export class ChatGateway {
@WebSocketServer()
server: Server;
@SubscribeMessage('broadcast')
handleBroadcast(@MessageBody() message: string): void {
this.server.emit('announcement', message);
}
}Socket yang Bersambung
Setiap klien mempunyai Socket sendiri. Suntikkannya bagi setiap pengendali dengan @ConnectedSocket() untuk membaca data pengesahan, id socket atau membalas hanya kepada klien tersebut.
client.emit(...)menyasarkan pengirim sahaja.client.idmengenal pasti sambungan secara unik.client.handshakemendedahkan pengepala, pertanyaan dan pengesahan yang dihantar semasa penyambungan.
import { WebSocketGateway, SubscribeMessage, MessageBody, ConnectedSocket } from '@nestjs/websockets';
import { Socket } from 'socket.io';
@WebSocketGateway({ namespace: '/chat' })
export class ChatGateway {
@SubscribeMessage('whoami')
whoAmI(@ConnectedSocket() client: Socket, @MessageBody() _: unknown): void {
client.emit('identity', { id: client.id, token: client.handshake.auth?.token });
}
}Cangkuk Kitar Hayat
Gateway boleh melaksanakan antara muka kitar hayat untuk bertindak balas terhadap peristiwa sambungan:
OnGatewayInit→afterInit(server)berjalan setelah server sedia.OnGatewayConnection→handleConnection(client)dicetuskan bagi setiap klien baharu.OnGatewayDisconnect→handleDisconnect(client)dicetuskan apabila klien meninggalkan sambungan.
Gunakan ini untuk menjejak kehadiran, pengesahan semasa penyambungan dan pembersihan.
import { WebSocketGateway, OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect } from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';
import { Logger } from '@nestjs/common';
@WebSocketGateway({ namespace: '/chat' })
export class ChatGateway implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect {
private readonly logger = new Logger(ChatGateway.name);
afterInit(server: Server): void {
this.logger.log('Gateway initialized');
}
handleConnection(client: Socket): void {
this.logger.log(`Client connected: ${client.id}`);
}
handleDisconnect(client: Socket): void {
this.logger.log(`Client disconnected: ${client.id}`);
}
}Room: Mengumpulkan Socket
Room ialah label pada sisi server yang anda lampirkan pada socket supaya anda boleh menyiarkan kepada sebahagian klien. Satu socket boleh menjadi anggota banyak room.
client.join('room')menambah socket ke dalam room.client.leave('room')mengeluarkannya.- Socket.IO secara automatik memasukkan setiap socket ke dalam room yang dinamakan mengikut
client.idsendiri.
Room membolehkan anda membina sembang mengikut saluran, papan pemuka mengikut penyewa atau kerjasama mengikut dokumen.
import { WebSocketGateway, SubscribeMessage, MessageBody, ConnectedSocket } from '@nestjs/websockets';
import { Socket } from 'socket.io';
@WebSocketGateway({ namespace: '/chat' })
export class ChatGateway {
@SubscribeMessage('joinRoom')
joinRoom(@ConnectedSocket() client: Socket, @MessageBody() room: string): void {
client.join(room);
client.emit('joined', room);
}
}Menyiarkan kepada Room
Sasarkan room dengan server.to('room').emit(...). Untuk mengecualikan pengirim, lakukan emit daripada socket klien: client.to('room').emit(...) menghantar kepada semua orang dalam room kecuali klien tersebut.
server.to(room).emit(...)→ semua orang dalam room.client.to(room).emit(...)→ semua orang dalam room kecuali pengirim.
import { WebSocketGateway, WebSocketServer, SubscribeMessage, MessageBody, ConnectedSocket } from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';
@WebSocketGateway({ namespace: '/chat' })
export class ChatGateway {
@WebSocketServer() server: Server;
@SubscribeMessage('sendToRoom')
sendToRoom(
@ConnectedSocket() client: Socket,
@MessageBody() body: { room: string; text: string },
): void {
client.to(body.room).emit('message', { from: client.id, text: body.text });
}
}Pengakuan dengan WsResponse
Socket.IO menyokong pengakuan bergaya permintaan/respons. Dalam Nest, anda boleh memulangkan nilai, objek WsResponse<T>, atau malah Observable yang menstrim berbilang emisi kembali.
- Pulangkan
{ event, data }untuk menghantar event bernama kembali kepada pemanggil. - Memulangkan
Observablemenghasilkan satu mesej bagi setiap nilai, sesuai untuk kemas kini kemajuan.
import { WebSocketGateway, SubscribeMessage, MessageBody, WsResponse } from '@nestjs/websockets';
import { from, Observable } from 'rxjs';
import { map } from 'rxjs/operators';
@WebSocketGateway({ namespace: '/jobs' })
export class JobsGateway {
@SubscribeMessage('countdown')
countdown(@MessageBody() n: number): Observable<WsResponse<number>> {
const ticks = Array.from({ length: n }, (_, i) => n - i);
return from(ticks).pipe(map((value) => ({ event: 'tick', data: value })));
}
}Pengesahan dengan Paip
Gateway menggunakan semula ValidationPipe Nest, tetapi ralat dilemparkan sebagai WsException, bukannya pengecualian HTTP. Gunakan paip pada peringkat pengendali atau gateway dan sahkan DTO melalui @MessageBody().
- Tetapkan
transform: truesupaya muatan biasa menjadi tika kelas. WsExceptiondisiri menjadi eventexceptionpada klien.
import { WebSocketGateway, SubscribeMessage, MessageBody } from '@nestjs/websockets';
import { UsePipes, ValidationPipe } from '@nestjs/common';
import { IsString, MinLength } from 'class-validator';
class SendMessageDto {
@IsString() @MinLength(1)
text: string;
}
@WebSocketGateway({ namespace: '/chat' })
export class ChatGateway {
@UsePipes(new ValidationPipe({ transform: true }))
@SubscribeMessage('send')
send(@MessageBody() dto: SendMessageDto): { event: string; data: string } {
return { event: 'sent', data: dto.text };
}
}Mengesahkan Pengguna Semasa Penyambungan
Sahkan klien semasa handleConnection dengan membaca token daripada jabat tangan dan memutuskan sambungan soket yang tidak dibenarkan lebih awal. Menyimpan pengguna pada client.data menjadikannya tersedia kepada setiap pengendali selepas itu.
- Token biasanya dihantar melalui
handshake.auth.tokenatau pengepalaAuthorization. - Panggil
client.disconnect()untuk menolak klien yang tidak sah sebelum mereka menyertai bilik.
import { WebSocketGateway, OnGatewayConnection } from '@nestjs/websockets';
import { Socket } from 'socket.io';
import { JwtService } from '@nestjs/jwt';
@WebSocketGateway({ namespace: '/chat' })
export class ChatGateway implements OnGatewayConnection {
constructor(private readonly jwt: JwtService) {}
async handleConnection(client: Socket): Promise<void> {
try {
const token = client.handshake.auth?.token as string;
client.data.user = await this.jwt.verifyAsync(token);
} catch {
client.emit('error', 'Unauthorized');
client.disconnect();
}
}
}Menukar Adapter untuk Skala
Secara lalai, keadaan Socket.IO berada dalam satu proses. Untuk menjalankan beberapa tika Nest di belakang pengimbang beban, anda mesti berkongsi keadaan bilik dan emit. Gunakan adapter tersuai bersama adapter Redis supaya siaran sampai kepada klien pada nod lain.
- Warisi
IoAdapterdan lampirkan@socket.io/redis-adapterdalamcreateIOServer. - Daftarkannya melalui
app.useWebSocketAdapter(new RedisIoAdapter(app))dalammain.ts.
import { IoAdapter } from '@nestjs/platform-socket.io';
import { ServerOptions } from 'socket.io';
import { createAdapter } from '@socket.io/redis-adapter';
import { createClient } from 'redis';
export class RedisIoAdapter extends IoAdapter {
private adapterConstructor: ReturnType<typeof createAdapter>;
async connectToRedis(): Promise<void> {
const pub = createClient({ url: 'redis://localhost:6379' });
const sub = pub.duplicate();
await Promise.all([pub.connect(), sub.connect()]);
this.adapterConstructor = createAdapter(pub, sub);
}
createIOServer(port: number, options?: ServerOptions): any {
const server = super.createIOServer(port, options);
server.adapter(this.adapterConstructor);
return server;
}
}Semakan Pantas
Uji pemahaman anda tentang semantik penyiaran bilik.
Imbas Kembali
Anda telah membina lapisan masa nyata dengan get laluan WebSocket NestJS pada adapter Socket.IO:
- Asas get laluan: penyedia
@WebSocketGateway()dengan pengendali@SubscribeMessage; suntik pelayan melalui@WebSocketServer()dan soket bagi setiap klien melalui@ConnectedSocket(). - Cangkuk kitar hayat:
afterInit,handleConnection, danhandleDisconnectuntuk permulaan, kehadiran, dan pembersihan. - Bilik:
client.join/leave, kemudianserver.to(room)untuk semua orang atauclient.to(room)untuk mengecualikan pengirim. - Keteguhan: sahkan muatan dengan
ValidationPipe(ralat menjadiWsException), lakukan pengesahan dalamhandleConnection, dan gunakan pengakuan/Observable untuk balasan. - Skala: gantikan dengan
IoAdapterberasaskan Redis supaya siaran berfungsi merentasi beberapa tika.
Pelajari TypeScript dengan tutor kecerdasan buatan — percuma
Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.
- Kursus
- 20
- Pelajaran
- 76
Soalan Lazim
Adakah pelajaran “Gerbang WebSocket dengan Penyesuai Socket.IO” percuma?
Ya — teks penuh “Gerbang WebSocket dengan Penyesuai Socket.IO” boleh dibaca secara percuma di web ini. Untuk berlatih secara interaktif menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7, serta membuka kunci baki kursus API Bahagian Belakang Perusahaan NestJS, tingkat taraf kepada CoddyKit PRO. Kursus API Bahagian Belakang Perusahaan NestJS merangkumi sejumlah 4 pelajaran.
Apakah yang akan saya pelajari dalam “Gerbang WebSocket dengan Penyesuai Socket.IO”?
Laksanakan pengendali @WebSocketGateway, bilik dan cangkuk kitar hayat untuk komunikasi langsung Anda berlatih API Bahagian Belakang Perusahaan NestJS menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.
Adakah saya memerlukan pengalaman untuk memulakan API Bahagian Belakang Perusahaan NestJS?
Tiada pengalaman terdahulu diperlukan. Pembelajaran API Bahagian Belakang Perusahaan NestJS di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 1 daripada 4.
Berapa lamakah pelajaran “Gerbang WebSocket dengan Penyesuai Socket.IO” diambil?
Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.
Bolehkah saya menulis dan menjalankan kod dalam pelajaran API Bahagian Belakang Perusahaan NestJS ini?
Ya. Setiap pelajaran API Bahagian Belakang Perusahaan NestJS menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.
Semua pelajaran dalam kursus ini
- Gerbang WebSocket dengan Penyesuai Socket.IO
- Mengesahkan dan Melindungi Sambungan Socket
- Peristiwa Dihantar Pelayan untuk Tolakan Sehala
- Menskalakan Masa Nyata dengan Penyesuai Redis Pub/Sub