本文主要总结nest中如何使用socket.io等WebSocket库, socket.io的使用可见socket.io
网关注解
要在nest中写websocket相关的代码, 需要创建一个被@WebSocketGateway()
装饰的类, 里面封装了websocket服务基本的API。
@WebSocketGateway({})
export class ChatGetWay {}
在类中有三个固定名称的钩子函数, 控制着websocket的生命周期:
- afterInit(), 参数为服务器实例
- handleConnection(), 参数为客户端实例
- handleDisconnect(), 参数为客户端实例
作用顾名思义。
Socket.io配置
在使用socket.io创建服务器时, 往往需要进行相关配置如跨域等
// server-side
const io = new Server(httpServer, {
cors: {
origin: "https://example.com",
allowedHeaders: ["my-custom-header"],
credentials: true
}
});
在nest中, 只需要将配置对象传入注解即可。
@WebSocketGateway({
cors: {
origin: '*',
methods: ['GET', 'POST']
},
namespace: 'chat'
})
在网关的第一个参数可以设置websocket的端口
@WebSocketGateway(80, { namespace: 'events' })
当然, 如果你不传入此参数, websocket服务器会自动挂载到nest启动的http服务器上, 监听相同的端口。
Socket.io业务
socket.io中最重要的就是发送和接收事件消息了。 在nest中, 需要使用@SubscribeMessage()
注解来装饰一个函数, 使其成为事件处理函数。
@SubscribeMessage('message') // 订阅`message`事件
handleMessage(
@ConnectedSocket() client, // 发送消息的客户端引用
@MessageBody() data // 事件携带的信息
) {
// do something
}
上面使用了两个注解来修饰事件处理函数的参数, 这是因为websocket网关是跨平台的, 平台不同, 客户端实例和消息格式也都可能不同。
socket.io服务器实例
要在nest中使用socket.io发送消息, 需要直接访问到服务器实例。
使用@WebSocketServer()
注解修饰成员变量, 即可获得服务器实例。
@WebSocketServer()
server: Server;
更多的与平台API相关的操作都可以通过服务器实例来完成。
this.server.to(group).emit('message', msg);
使用WebSocket服务
WebSocket网关类是特殊的Provider,也就是类似于被@Injectable()
的类, 使用上是类似的。可以通过构造函数注入其它Service、被模块管理, 也可以被注入。
websocket和http同端口时的跨域问题
如果你的后端中http和websocket是使用的同一端口, 即时你nest实例和websocket网关都配置了跨域, 你在使用客户端的时候还是会发生跨域。
这是以为socket.io客户端进行连接时, 首先会尝试建立HTTP长轮询连接, 连接成功后才会尝试建立WebSocket连接。
而同一端口已经存在了处理HTTP的服务器, 因此客户端尝试建立HTTP长轮询时, 就会发生错误。
解决办法是, 在客户端创建连接时配置, 只允许建立WebSocket连接。
const connection = io(url, {transports: ['websocket'] });
或者, 给socket.io服务器一个单独的端口。