nest.js项目集成websocket服务

2021-12-06 11:19:04 浏览数 (3)

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的方法,希望对你有所帮助。

0 人点赞