带你入门——如何在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的使用,并且能够和客户端进行连接

相关文章
|
前端开发 安全
FastAPI 学习之路(四十五)WebSockets
FastAPI 学习之路(四十五)WebSockets
FastAPI 学习之路(四十五)WebSockets
|
5月前
|
移动开发 JavaScript 网络协议
SpringBoot:Netty-SocketIO + VUE:SocketIO实现前后端实时双向通信
SpringBoot:Netty-SocketIO + VUE:SocketIO实现前后端实时双向通信
139 0
|
监控 小程序 安全
Uniapp使用GoEasy实现websocket实时通讯
GoEasy上架DCloud Uniapp插件市场已经有一个多月了,收到很多Uniapp开发人员的赞扬和好评。本篇文章将讲解在Uniapp下如何使用GoEasy完成第一个简单的实时通讯demo。
|
7月前
|
移动开发 前端开发 网络协议
WebSocket从入门到实战
WebSocket从入门到实战
174 0
|
9月前
|
移动开发 小程序 Java
良心分享:基于Java+SpringBoot+Netty+WebSocket+Uniapp轻松搭建在线互动问答程序
本文将详细介绍如何基于你自己的开源项目搭建一个在线互动问答程序,包括微信小程序和H5网页版。 该项目服务端主要使用了Java + Spring Boot + Netty + WebSocket等技术栈,聊天客户端使用的是UniApp来轻松搭建微信小程序和H5网页端。
39 1
|
9月前
|
开发框架 JavaScript 前端开发
如何使用SpringBoot和Netty实现一个WebSocket服务器,并配合Vue前端实现聊天功能?
如何使用SpringBoot和Netty实现一个WebSocket服务器,并配合Vue前端实现聊天功能?
199 0
|
前端开发 Java 应用服务中间件
SpringBoot整合Netty搭建高性能Websocket服务器(实现聊天功能)
之前使用Springboot整合了websocket,实现了一个后端向前端推送信息的基本小案例,这篇文章主要是增加了一个新的框架就是Netty,实现一个高性能的websocket服务器,并结合前端代码,实现一个基本的聊天功能。你可以根据自己的业务需求进行更改。 这里假设你已经了解了Netty和websocket的相关知识,仅仅是想通过Springboot来整合他们。根据之前大家的需求,代码已经上传到了github上。在文末给出。 废话不多说,直接看步骤代码。
1583 0
SpringBoot整合Netty搭建高性能Websocket服务器(实现聊天功能)
|
存储 JavaScript 网络协议
WebSocket接口初体验
这两天在调试一个WebSocket的接口,折腾了一天的时间终于弄好了。现在对WebSocket的相关知识点做一个记录。主要从如下几个方面进行介绍。
253 0
WebSocket接口初体验
|
前端开发 Python
Flask学习与实战11:WebSocket的使用与简单通信
用这个协议最方便的就是,服务器主动向客户端推送信息。客户端也可以主动向服务器发送信息。属于应用层协议,在握手阶段还是使用了HTTP的协议。
Flask学习与实战11:WebSocket的使用与简单通信
|
JSON 前端开发 JavaScript
使用NestJS搭建服务端应用(下)
使用NestJS搭建服务端应用(下)
使用NestJS搭建服务端应用(下)