简介

本文服务端以 Nest 官网模板,客户端以 Vue3 + Vite 官网模板为例,简略介绍如何在 Nest 我的项目中应用 socket.io 与 Vue3 的客户端进行即时通讯。

初始化我的项目

服务端

# 装置Nest脚手架$ npm i -g @nestjs/cli# 创立一个nest后端我的项目$ nest new project-name# 启动我的项目$ yarn start:dev

创立结束后:

# 服务端初始目录构造:src ├── app.controller.spec.ts ├── app.controller.ts ├── app.module.ts ├── app.service.ts └── main.ts

客户端

# 装置vite脚手架$ npm init vite@latest# 创立一个vue前端端我的项目$ npm init vite@latest my-vue-app -- --template vue# 启动我的项目$ yarn dev

创立结束后:

# 客户端初始目录构造:src ├── assets ├── components ├── App.vue └── main.ts

装置所需依赖

服务端

# 装置官网提供的socket.io包$ yarn add @nestjs/websockets @nestjs/platform-socket.io

客户端

# 装置官网提供的socket.io包$ yarn add socket.io-client

留神:

  • Nest v7及以下版本依赖于socket.io v2Nest v8依赖于socket.io v4,请留神查看版本的兼容性。
  • 服务端和客户端socket.io依赖包版本必须保持一致,否则将有可能无奈连贯或者报跨域等谬误。

配置 websocket

服务端

# 应用官网cli工具在我的项目中生成一个websocket模块。$ nest g res socketTest

主动生成模块之后,我的项目目录是这样的:

src ├── socket-test      ├── dto      ├── entities      ├── socket-test.gateway.spec.ts      ├── socket-test.gateway.ts      ├── socket-test.module.ts      ├── socket-test.service.spec.ts      ├── socket-test.service.ts ├── app.controller.spec.ts ├── app.controller.ts ├── app.module.ts ├── app.service.ts └── main.ts

关上socket-test.gateway.ts文件,内容如下:

import {  WebSocketGateway,  SubscribeMessage,  MessageBody,} from "@nestjs/websockets";import { SocketTestService } from "./socket-test.service";import { CreateSocketTestDto } from "./dto/create-socket-test.dto";import { UpdateSocketTestDto } from "./dto/update-socket-test.dto";/** @WebSocketGateway装璜器可传入一些配置选项,如上面的示例: *   @WebSocketGateway(80, { *     namespace: 'events', *     transports: ['websocket'] *     cors: { *        origin: '*' *     }, *     ... *   }) **/@WebSocketGateway({ cors: true })export class SocketTestGateway {  constructor(private readonly socketTestService: SocketTestService) {}  @SubscribeMessage("createSocketTest")  create(@MessageBody() createSocketTestDto: CreateSocketTestDto) {    return this.socketTestService.create(createSocketTestDto);  }  @SubscribeMessage("findAllSocketTest")  findAll() {    return this.socketTestService.findAll();  }  @SubscribeMessage("findOneSocketTest")  findOne(@MessageBody() id: number) {    return this.socketTestService.findOne(id);  }  @SubscribeMessage("updateSocketTest")  update(@MessageBody() updateSocketTestDto: UpdateSocketTestDto) {    return this.socketTestService.update(      updateSocketTestDto.id,      updateSocketTestDto    );  }  @SubscribeMessage("removeSocketTest")  remove(@MessageBody() id: number) {    return this.socketTestService.remove(id);  }}

客户端

在 src 目录下创立 plugins 文件夹,于其中新建一个 Socket.io.ts 插件,

src ├── assets ├── components ├── plugins      ├── Socket.io.ts ├── App.vue └── main.ts

在 Socket.io.ts 文件中写入上面的内容,

// Socket.io.tsimport { io } from "socket.io-client";export default {  install: (app, { connection, options }) => {    const socket = io(connection, options);    app.config.globalProperties.$socket = socket;    app.provide("socket", socket);  },};

而后在 main.ts 文件中引入进来,挂载到 app 上,

// main.tsimport { createApp } from "vue";import App from "./App.vue";import Socketio from "/@/plugins/Socket.io";const app = createApp(App);app.use(Socketio, {  connection: "/* 这里填写服务端地址,如 http://localhost:3000 */",  options: {    autoConnect: false, //敞开主动连贯    // ...其它选项  },});app.mount("#app");

而后在须要的时候应用socket.connect()手动连贯 socket。

理论使用

Nest 在应用@SubscribeMessage装璜的办法中,会return一个确认信息,咱们能够间接返回 JSON 格局或是字符串格局数据,比方咱们增加一个测试事件:

// 服务端 socket-test.gateway.ts@SubscribeMessage('socketTest')socketTest(@MessageBody() data: any) {  Logger.log(data) // {test: '测试数据'}  return {    msg1: '测试1',    msg2: '测试2',  }}----------------------------------// 客户端 HelloWorld.vueimport { ref, onMounted, inject } from 'vue';import { Socket } from 'socket.io-client';const socket = inject('socket') as Socket;socket.emit('socketTest', {test: '测试数据'}, (data) => {  console.log(data) // { msg1: '测试1', msg2: '测试2' }});onMounted(() => {  socket.connect(); //连贯socket服务器});

有时候可能须要在客户端发送音讯后,让服务端把音讯再转发给客户端的另一个事件中,咱们能够在 return 的时候减少一个指定事件 event,而后在客户端进行监听,比方:

// 服务端 socket-test.gateway.ts@SubscribeMessage('socketTest')socketTest(@MessageBody() data: any) {  return {    event: 'socketTest2',    data  }}----------------------------------// 客户端 HelloWorld.vueimport { ref, onMounted, inject } from 'vue';import { Socket } from 'socket.io-client';const socket = inject('socket') as Socket;socket.emit('socketTest',{ msg1: '测试1', msg2: '测试2' })socket.on('socketTest2', (data) => {  console.log(data) // { msg1: '测试1', msg2: '测试2' }});onMounted(() => {  socket.connect(); //连贯socket服务器});

下面尽管解决了客户端与服务端互相通信的问题,但实际上咱们的我的项目可能不会这么简略,有可能是socket.id不同的多个客户端,这种状况下咱们就须要应用@nestjs/websockets包导出的@ConnectedSocket()装璜器,获取到 socket.io 的实例,应用官网提供的一些 Api 来定义事件,以播送事件为例:

// 服务端 socket-test.gateway.ts@SubscribeMessage('socketTest')socketTest(@MessageBody() data: any, @ConnectedSocket() clinet: Socket) {  clinet.broadcast.emit('socketTest2', data);}----------------------------------// 客户端-1 HelloWorld.vueimport { ref, onMounted, inject } from 'vue';import { Socket } from 'socket.io-client';const socket = inject('socket') as Socket;socket.emit('socketTest',{ msg1: '测试1', msg2: '测试2' })socket.on('socketTest2', (data) => {  console.log(data) // { msg1: '测试1', msg2: '测试2' }});onMounted(() => {  socket.connect(); //连贯socket服务器});----------------------------------// 客户端-2 Layout.vueimport { ref, onMounted, inject } from 'vue';import { Socket } from 'socket.io-client';const socket = inject('socket') as Socket;socket.on('socketTest2', (data) => {  console.log(data) // { msg1: '测试1', msg2: '测试2' }});onMounted(() => {  socket.connect(); //连贯socket服务器});

本文首次公布在https://www.cnblogs.com/China-Dream/p/15827701.html