简介
本文服务端以 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 v2
,Nest 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.ts
import {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.ts
import {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.vue
import {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.vue
import {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.vue
import {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.vue
import {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