nest.js项目集成websocket服务的话,需要安装相关的npm包,如下:
代码语言:javascript复制npm i --save @nestjs/websockets @nestjs/platform-socket.io
一个是@nestjs/websockets,一个是@nestjs/platform-socket.io。
在nestjs项目中,我们将websocket服务集成为一个模块,这个模块中集成的服务便是配置websocket的文件,websocket这个类必须用@WebSocketGateway装饰器修饰,本质也是一个服务,即配置在providers中的类。
websocket的服务类一般会有一个成员属性和N个方法,成员属性其实就是websocket服务器的实例,而方法都是订阅特定事件的方法,成员对象用@WebSocketServer装饰器修饰,而方法都会用@SubscribeMessage装饰器来装饰。示例代码如下:
代码语言:javascript复制import {
MessageBody,
SubscribeMessage,
WebSocketGateway,
WebSocketServer,
WsResponse,
} from '@nestjs/websockets';
import { from, Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Server } from 'socket.io';
@WebSocketGateway(8080,{
cors: {
origin: '*',
},
})
export class EventsGateway {
@WebSocketServer()
server: Server;
@SubscribeMessage('events')
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
findAll(@MessageBody() data: any): Observable<WsResponse<number>> {
console.log('我执行了两次');
console.log('接收消息events的数据',data)
return from([1, 2, 3]).pipe(map(item => ({ event: 'events', data: item })));
}
@SubscribeMessage('identity')
async identity(@MessageBody() data: number): Promise<number> {
console.log('接收identity的数据', data)
// await new Promise((reslove,reject)=>{
// setTimeout(reslove,2000)
// })
return 1;
}
PublicMessage(message:string) :void{
setInterval(() => {
this.server.emit("exception",`我是服务端发来的消息${message}`)
}, 1000)
}
}
注意@WebSocketGateway修饰器一般需要传递两个参数,第一个参数为websocket服务器监听的端口,第二个参数为设置cors响应头,这样浏览器就不会组织跨越了。
这里有个技巧,如果第一个参数设置的和http服务器相同,启动时会报错,显示端口被占用,如果不设置第一个参数,那么默认的端口和http服务器端口相同,但是不会报端口被占用的错误。
WebSocketServer这个装饰器的作用是使Nest框架自动将服务器实例分配给指定属性。上文将服务器实例分配给了server。
SubscribeMessage装饰器必须传递一个参数,这个参数就是订阅的事件名称,客户端向这个事件发送消息,服务器这里就能订阅到了。
我看看一下websocket文件模块结构:
只需要一个网关(在nestjs项目中将websocket称为网关)文件和一个module文件,网关文件内容就是上面代码。
我们要将websocket这个模块配置成共享模块,只需要在module文件中做如下配置:
只需要在exports中导出服务本身,这样的话,如果其他模块要使用websocket这个模块中的服务的话,只需要在其他模块中导入websocket模块即可,假如我们要在posts模块中使用websocket模块,只需要如下配置:
之后在需要使用websocket模块的服务的地方将其依赖导入即可,其他模块使用websocket模块,本质上使用的事websocket模块的方法,假如在posts的控制器中我们需要使用websocket的服务,只需将其以来导入即可,代码如下:
有些同学要问为什么这么麻烦,直接将服务依赖注入到使用的地方不可以吗,答案显示是不可以,配置共享模块视为了在所有模块中共享websocket模块的实例,如果省略这一步,websocket实例就会多次被实例化,而配置了共享模块,在使用前先导入模块,到依赖注入服务,websocket模块就不会多次实力化了。说到底这事一个规则。
文章思维导图:
以上便是在nestjs项目中集成websocket的方法,希望对你有所帮助。