带你入门——如何在nestjs中体验websocket

简介: 带你入门——如何在nestjs中体验websocket

前言准备

在nestjs官方文档中提到,在nestjs中有两个现成支持的 WS 平台:socket.iows,这俩都是基于websocket封装的框架,其中socket.io在websocket的基础上集成了强大的功能

  1. 实时双向通信:Socket.IO 提供了实时的双向通信,允许服务器主动向客户端发送消息,并且客户端也可以向服务器发送消息。这种双向通信方式非常适合实时应用程序的需求,例如聊天或协作工具。
  2. 自动重新连接:当客户端与服务器之间的连接中断时,Socket.IO 具有自动重新连接的能力,它会尝试重新建立连接,并维护连接的稳定性。
  3. 分房间/分组:Socket.IO 允许将客户端连接划分到不同的房间或分组中,可以根据不同的需求将客户端进行分组管理,并实现群发或与特定组进行通信。
  4. 自定义事件:Socket.IO 允许开发者定义和触发自定义事件,这些事件可以是应用程序内部的逻辑事件或用户自定义的事件。通过自定义事件,可以实现灵活的消息传递和通信模式。
  5. 跨平台支持:Socket.IO 不仅支持浏览器端,还支持服务器端的多种编程语言,如 Node.js、Python、Java 和 .NET 等。这使得开发者能够在不同的环境中使用相同的通信协议和模式。

并且当 WebSocket 连接不可用时,Socket.IO 会使用 HTTP 协议作为备选方案来保持实时通信。

这俩框架选谁都可以,我这里用socket.io来为大家做演示了。

构建准备

先安装对应的包


pnpm i --save @nestjs/websockets @nestjs/platform-socket.io

接着通过创建一个gateway模块,与此同时创建一个event.gateway.ts,用于创建我们的websocket服务

image.png

接着在我们的event.gateway.ts中创建我们的类


import {WebSocketGateway} from '@nestjs/websockets'
@WebSocketGateway()
export class EventGateway  {
}

@WebSocketGateway是一个装饰器,用于创建WebSocket网关类。WebSocket网关类是用于处理 WebSocket连接和消息的核心组件之一。它充当WebSocket服务端的中间人,负责处理客户端发起的连接请求,并定义处理不同类型消息的逻辑

对于它可以接受一些参数,这里我们就快速过一遍挑重要的说 @WebSocketGateway(80, options)

第一个参数可以传递一个端口号,如果不传默认和http监听的端口一样,也就是main.ts中的端口,nestjs默认是3000,第二个是一些配置项,有很多例如跨域配置cors,以及namespace命名空间,这里只说配置cors跨域,其他的配置项,可以自行去[服务器选项 |Socket.IO]看看

在现在的新版本中客户端连接nestjs端的websocket服务时会出现跨域问题的,所以需要配置一下


@WebSocketGateway({
        cors: {
                origin: '*',
        },
})

配置完这些,我们还需要在module中提供一下,因为网关可以被视为provider,可以注入依赖项,也可以被其他类注入


import { Module } from '@nestjs/common';
import { EventGateway } from './enent.gateway';
@Module({
   providers: [EventGateway]
})
export class GatewayModule {}

实现订阅消息

到这里我们就配置好了,但是我们想想一个最简易的聊天是不是得有发送消息和接收消息吧,就是发布订阅模式,nestjs中为我们内置好了对应的装饰器 @SubscribeMessage,看到这个英文单词就知道啥意思了,就是订阅消息的意思,在我们订阅到消息时可以写一下逻辑处理


import { MessageBody, SubscribeMessage, WebSocketGateway } from '@nestjs/websockets'
@WebSocketGateway({ cors: { origin: '*' } })
export class EventGateway {
        @SubscribeMessage('newMessage')
        handleMessage(@MessageBody() body: any) {
                console.log(body);
        }
}

@MessageBody这个装饰器可以获取消息,到这里我们的订阅服务已经起来了,打开控制台启动一下项目看看

image.png

看到里面有Websocketscontroller就代表启动成功了

如果不想用装饰器可以这样做,效果一样


@SubscribeMessage('events')
handleEvent(client: Socket, data: any): any {
  return data;
}

第一个参数是socket实例,第二个data是从客户端接受的消息,但是官方不推荐这种写法哈,建议还是用装饰器

实现发布消息

那么处理好了订阅消息,如何实现发布消息呢,官方文档中介绍了一个装饰器 @ConnectedSocket,可以实例化一个socket,我们可以通过上面的emit方法来监听一个自定义事件来发布消息


import { ConnectedSocket, MessageBody, SubscribeMessage, WebSocketGateway } from '@nestjs/websockets'
import { Socket } from 'socket.io'
@WebSocketGateway({ cors: { origin: '*' } })
export class EventGateway {
        @SubscribeMessage('newMessage')
        handleMessage(@MessageBody() body: any, @ConnectedSocket() client: Socket,) {
                client.emit('onMessage')
                console.log(body);
        }
}

接着打开postman来测试,我推荐这款工具的原因是,我在apifox中发现对websocket的支持不好,而且在postman中有对socket.io专门的测试。下面带着大家上手试试

image.png

image.png

image.png

image.png

经过这些操作我们就拿到了发出的消息 注意要订阅的是newMessage也就是subscribe装饰器的参数

下面介绍另外一种,借助WebsocketServer


import { ConnectedSocket, MessageBody, SubscribeMessage, WebSocketGateway, WebSocketServer } from '@nestjs/websockets'
import { Server, Socket } from 'socket.io'
@WebSocketGateway({ cors: { origin: '*' } })
export class EventGateway {
        @WebSocketServer()
        server: Server
        @SubscribeMessage('newMessage')
        handleMessage(@MessageBody() body: any, @ConnectedSocket() client: Socket,) {
                this.server.emit('onMessage', {
                        msg: 'new Message',
                        content: body
                })
        }
}

实现的效果一样的。

利用SocketClient创建客户端

接下来利用postman模拟客户端

新开一个nestjs服务,注意mian.ts中的端口号改一下,别冲突了,创建一个socket模块,跟上面步骤一样


import { Module } from '@nestjs/common';
import { SocketClient } from './socket-client';
@Module({
        providers: [SocketClient]
})
export class SocketModule { }

下面在socket-client.ts中创建如下代码

image.png

import { Injectable, OnModuleInit } from "@nestjs/common";
import { io, Socket } from 'socket.io-client'
@Injectable()
export class SocketClient implements OnModuleInit {
        public socketClient: Socket
        constructor() {
                this.socketClient = io('http://localhost:3000')
        }
        onModuleInit() {
                this.registerConsumerEvent()
        }
        private registerConsumerEvent() {
                this.socketClient.on('connect', () => {
                        console.log('connect to gateway');
                })
                this.socketClient.on('onMessage', (payload: any) => {
                        console.log('socketClientClass');
                        console.log(payload);
                })
        }
}

我们这里构造了一个socketClient客户端, OnMouleInit是nestjs的生命周期函数,就是模块初始化时,我们调用了registerConsumerEvent()函数,在这个函数内,我们做了两件事,第一件事,在连接时,做 了逻辑处理,第二件事,监听了onMessage事件,并且能够别人发布的值,接着利用postman来测试一下

image.png

也是输入url连接之后,需要选监听的events,打开listen 做到这样就可以了,我们从第一个服务中发送一条消息试试

image.png

可以看到监听到了数据,到此我们已经做完了利用socketClient构造客户端

vue3搭配nestjs实现websocket小demo

首先在前端中导入包


pnpm i socket.io-client

之后我们直接在socket.io的官网拿到vue3模板

image.png

import { reactive } from "vue";
import { io } from "socket.io-client";
export const state = reactive
  <{
    connected: boolean
    fooEvents: Array<any>
    barEvents: Array<any>
  }>
  ({
    connected: false,
    fooEvents: [],
    barEvents: []
  });
const URL = "http://localhost:3000"
export const socket = io(URL);
socket.on("connect", () => {
  state.connected = true;
});
socket.on("disconnect", () => {
  state.connected = false;
});
socket.on("foo", (...args) => {
  state.fooEvents.push(args);
});
socket.on("bar", (...args) => {
  state.barEvents.push(args);
});

接着在app.vue中引入

<script setup lang="ts">
import { onBeforeMount, onMounted, onUnmounted, reactive } from 'vue';
import { socket } from './socket'
const chatList = reactive<{
  value: string
  list: Array<any>
}>({
  value: '',
  list: []
})
// 组件挂载前让socket连接起来
onBeforeMount(() => {
  socket.connect();
});
// 组件挂载完毕完成后,监听onMessage事件
onMounted(() => {
  socket.on("onMessage", (e) => {
    console.log(e);
    chatList.list.push(e.content);
  });
});
// 组件销毁时断开连接
onUnmounted(() => {
  socket.disconnect();
});
// 点击btn发送socket消息
const handleClick = () => {
  socket.emit("newMessage", chatList.value, (e: any) => {
    console.log(e);
  });
};
</script>
<template>
  <div>
    <input v-model="chatList.value" />
    <button @click="handleClick()" style="margin-left: 12px;">发送</button>
    <div >
      <ul>
        <li v-for="(item, index) in chatList.list" :key="index">{{ item }}</li>
      </ul>
    </div>
  </div>
</template>
<style scoped>
header {
  line-height: 1.5;
}
.logo {
  display: block;
  margin: 0 auto 2rem;
}
@media (min-width: 1024px) {
  header {
    display: flex;
    place-items: center;
    padding-right: calc(var(--section-gap) / 2);
  }
  .logo {
    margin: 0 2rem 0 0;
  }
  header .wrapper {
    display: flex;
    place-items: flex-start;
    flex-wrap: wrap;
  }
}
</style>

到此我们就配置完成了,接下来看看效果吧

image.png

image.png

image.png

到此我们就实现了websocket在nestjs的使用,并且能够和客户端进行连接

相关文章
|
2月前
|
网络协议 前端开发 JavaScript
WebSocket 教程汇总指南,从入门到熟练
本文将带你从零开始,逐步掌握 WebSocket 的基本概念、实现方法和应用场景,通过一系列详细的教程和实践案例,帮助你从入门到熟练地使用 WebSocket 技术。无论你是初学者还是有一定经验的开发者,本文都能为你提供有价值的信息和指导。
|
2月前
|
网络协议 安全 JavaScript
Web实时通信的学习之旅:WebSocket入门指南及示例演示
Web实时通信的学习之旅:WebSocket入门指南及示例演示
219 0
|
4月前
|
前端开发 网络协议 物联网
Django Web:搭建Websocket服务器(入门篇)
Django Web:搭建Websocket服务器(入门篇)
113 1
|
4月前
|
网络协议 前端开发 Go
[go笔记]websocket入门
[go笔记]websocket入门
|
7月前
|
小程序 Java 编译器
性能工具之JMeter 微信小程序 WebSocket 脚本入门
【5月更文挑战第12天】性能工具之JMeter 微信小程序 WebSocket 脚本入门
223 1
|
前端开发 Java Maven
springboot整合websocket最基础入门使用教程详解
springboot整合websocket最基础入门使用教程详解
3551 0
springboot整合websocket最基础入门使用教程详解
|
缓存 移动开发 安全
WebSocket协议:5分钟从入门到精通
WebSocket协议:5分钟从入门到精通
221 0
|
移动开发 前端开发 网络协议
WebSocket从入门到实战
WebSocket从入门到实战
280 0
|
存储
Netty入门到超神系列-基于WebSocket开发聊天室
在很多的网站中都嵌入有聊天功能,最理想的方式就是使用WebSocket来开发,屏幕面前的你如果不清楚WebSocket的作用可以自己去百度一下,Netty提供了WebSocket支持,这篇文章将使用Netty作为服务器,使用WebSocket开发一个简易的聊天室系统。
263 0
|
网络协议 前端开发 Java
Spring / Boot整合 WebSocket-入门Demo
Spring / Boot整合 WebSocket-入门Demo
238 0
下一篇
DataWorks