brief introduction
In this paper, the server takes Nest official template and the client takes Vue3 + Vite official template as an example to briefly introduce how to use socket in Nest project IO instant messaging with Vue3's clients.
Initialize project
Server
# Install Nest scaffold $ npm i -g @nestjs/cli # Create a nest backend project $ nest new project-name # Start project $ yarn start:dev
After creation:
# Initial directory structure of server: src ├── app.controller.spec.ts ├── app.controller.ts ├── app.module.ts ├── app.service.ts └── main.ts
client
# Installation of vite scaffold $ npm init vite@latest # Create a vue front-end project $ npm init vite@latest my-vue-app -- --template vue # Start project $ yarn dev
After creation:
# Client initial directory structure: src ├── assets ├── components ├── App.vue └── main.ts
Install required dependencies
Server
# Install the official socket IO package $ yarn add @nestjs/websockets @nestjs/platform-socket.io
client
# Install the official socket IO package $ yarn add socket.io-client
be careful:
- Nest v7 and below depend on socket IO V2 and Nest v8 depend on socket IO V4, please check the compatibility of the version.
- Server and client socket The IO dependent package version must be consistent, otherwise it may fail to connect or report cross domain errors.
Configure websocket
Server
# Use the official cli tool to generate a websocket module in the project. $ nest g res socketTest
After the module is automatically generated, the project directory is as follows:
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
Open socket test gateway. TS file, as follows:
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 The decorator can pass in some configuration options, such as the following example: * @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); } }
client
Create a plugins folder in the src directory and create a new socket io. TS plug-in,
src ├── assets ├── components ├── plugins ├── Socket.io.ts ├── App.vue └── main.ts
In socket io. Write the following contents in the TS file,
// 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); }, };
Then in main TS file and mount it on the 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: "/* Fill in the server address here, such as http://localhost:3000 */", options: { autoConnect: false, //Turn off automatic connection // ... Other options }, }); app.mount("#app");
Then use socket when necessary Connect() manually connects the socket.
Practical application
Nest will return a confirmation message in the method decorated with @ SubscribeMessage. We can directly return data in JSON format or string format. For example, we add a test event:
// Server socket test gateway. ts @SubscribeMessage('socketTest') socketTest(@MessageBody() data: any) { Logger.log(data) // {test: 'test data'} return { msg1: 'Test 1', msg2: 'Test 2', } } ---------------------------------- // Client HelloWorld vue import { ref, onMounted, inject } from 'vue'; import { Socket } from 'socket.io-client'; const socket = inject('socket') as Socket; socket.emit('socketTest', {test: 'test data'}, (data) => { console.log(data) // {msg1: 'test 1', msg2: 'test 2'} }); onMounted(() => { socket.connect(); //Connect to socket server });
Sometimes it may be necessary to ask the server to forward the message to another event of the client after the client sends the message. We can add a specified event event when return ing, and then listen on the client, such as:
// Server socket test gateway. ts @SubscribeMessage('socketTest') socketTest(@MessageBody() data: any) { return { event: 'socketTest2', data } } ---------------------------------- // Client HelloWorld vue import { ref, onMounted, inject } from 'vue'; import { Socket } from 'socket.io-client'; const socket = inject('socket') as Socket; socket.emit('socketTest',{ msg1: 'Test 1', msg2: 'Test 2' }) socket.on('socketTest2', (data) => { console.log(data) // {msg1: 'test 1', msg2: 'test 2'} }); onMounted(() => { socket.connect(); //Connect to socket server });
Although the above solves the problem of communication between client and server, in fact, our project may not be so simple, it may be socket For multiple clients with different IDS, we need to use the @ ConnectedSocket() decorator exported from the @ nestjs/websockets package to obtain the socket For the instance of IO, some APIs provided by the government are used to define events. Take broadcast events as an example:
// Server socket test gateway. ts @SubscribeMessage('socketTest') socketTest(@MessageBody() data: any, @ConnectedSocket() clinet: Socket) { clinet.broadcast.emit('socketTest2', data); } ---------------------------------- // Client-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: 'Test 1', msg2: 'Test 2' }) socket.on('socketTest2', (data) => { console.log(data) // {msg1: 'test 1', msg2: 'test 2'} }); onMounted(() => { socket.connect(); //Connect to socket server }); ---------------------------------- // Client - 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: 'test 1', msg2: 'test 2'} }); onMounted(() => { socket.connect(); //Connect to socket server });
This article was first published in https://www.cnblogs.com/China-Dream/p/15827701.html