前言
最近在做一个 H5 仿新版 QQ 的一个项目,使用的技术栈为 Vue3 + TypeScript + Vite + Pinia + Naive UI
其中最主要的核心功能就是 WebSocket,建立长连接,实现即时通信效果
正文
首先在src/utils
下新建一个 websocket.ts
文件,里面是封装的 websocket 类(其中部分功能需要根据自己业务需求修改)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
| class WebSocketClass { private wsurl: string; private id: number; private socketTask: WebSocket | null = null; private isConnected: boolean = false; private heartbeatIntervalId: ReturnType<typeof setInterval> | null = null; private reconnectTimeoutId: ReturnType<typeof setTimeout> | null = null;
constructor( wsurl: string, id: number, private heartbeatInterval: number = 3 ) { this.wsurl = wsurl; this.id = id; this.connect(); }
private connect(): void { this.socketTask = new WebSocket(this.wsurl);
this.socketTask.onopen = () => { console.log("WebSocket连接成功!");
this.isConnected = true; this.startHeartbeat(); };
this.socketTask.onmessage = (messageEvent) => { console.log("接收到WebSocket消息:", JSON.parse(messageEvent.data)); const newMessage = JSON.parse(messageEvent.data); ... };
this.socketTask.onerror = () => { console.error("WebSocket连接错误!"); this.isConnected = false; };
this.socketTask.onclose = () => { console.log("WebSocket连接已关闭!"); const isLogin = JSON.parse(localStorage.getItem("user") as string).isLogin; this.isConnected = false; if (isLogin) { this.tryReconnect(); } }; }
private startHeartbeat(): void { if (this.heartbeatIntervalId) clearInterval(this.heartbeatIntervalId); this.heartbeatIntervalId = setInterval(() => { if (this.socketTask && this.isConnected) { const heartbeatMessage = { Action: "1", Sender: this.id, }; this.socketTask.send(JSON.stringify(heartbeatMessage)); console.log("发送心跳检测消息:", heartbeatMessage); } }, this.heartbeatInterval * 1000); }
private tryReconnect(): void { if (this.reconnectTimeoutId) clearTimeout(this.reconnectTimeoutId); this.reconnectTimeoutId = setTimeout(() => { console.log("尝试重新连接WebSocket..."); this.connect(); }, 5000); }
send(message: string): void { if (this.socketTask && this.isConnected) { this.socketTask.send(message); } else { console.error("发送失败:WebSocket未连接或已关闭。"); } }
close(): void { if (this.heartbeatIntervalId) clearInterval(this.heartbeatIntervalId); if (this.reconnectTimeoutId) clearTimeout(this.reconnectTimeoutId);
if (this.socketTask && this.isConnected) { this.socketTask.close(); this.socketTask = null; }
this.isConnected = false; } }
export default WebSocketClass;
|
定义接口
1 2 3 4
| export interface IWebSocket { send(message: string): void; close(): void; }
|
如何使用
在需要使用的组件中,进行引入,初始化实例
1 2 3 4 5 6 7 8
| import type { IWebSocket } from "@/model/xxx"; import websocket from "@/utils/websocket.ts";
const ws: IWebSocket = new websocket( `ws://xxxx/ws?id=${userInfo.uid}`, userInfo.uid ) as IWebSocket;
|
此时已经建立连接
会自动进行心跳检测
需要进行通信时,调用send()
发送消息