1.配置连接
websocket.ts文件如下
import { ElMessage } from "element-plus";
interface WebSocketProps {
url: string; // websocket地址
heartTime?: number; // 心跳时间间隔,默认为 50000 ms
heartMsg?: string; // 心跳信息,默认为'ping'
reconnectCount?: number; // 重连次数,默认为 5
reconnectTime?: number; // 重连时间间隔,默认为 10000 ms
message: (ev: MessageEvent) => any; // 接收消息的回调
open?: (ev: Event) => any; // 连接成功的回调
close?: (ev: CloseEvent) => any; // 关闭的回调
error?: (ev: Event) => any; // 错误的回调
}
// webSocket 对象
let webSocket: WebSocket | null = null;
// webSocket定时器id
let setIntervalId: NodeJS.Timeout | null = null;
export const initWebSocket = (config: WebSocketProps) => {
if (typeof WebSocket === "undefined") {
ElMessage.error("您的浏览器不支持Websocket通信协议,请使用Chrome或者其他高版本的浏览器!");
return;
}
if (webSocket != null && webSocket.readyState === webSocket.OPEN) {
return webSocket;
}
createWebSocket(config);
return webSocket;
};
/**
* 创建WebSocket
* @param config
*/
const createWebSocket = (config: WebSocketProps) => {
// 初始化 WebSocket
webSocket = new WebSocket(config.url);
webSocket.onopen = (ev: Event) => {
config.open && config.open(ev);
/**
* 发送心跳
* 使用Nginx代理WebSocket的时候,客户端与服务器握手成功后,如果在60秒内没有数据交互,就会自动断开连接。
* Nginx默认的断开链接时间为60秒
*/
sendPing(config.heartTime ?? 50000, config.heartMsg ?? "ping");
};
webSocket.onmessage = (ev: MessageEvent) => config.message(ev);
webSocket.onerror = (ev: Event) => error(config, ev);
webSocket.onclose = (ev: CloseEvent) => close(config, ev);
};
/**
* 发送心跳
* @param {number} heartTime 心跳间隔毫秒 默认50000
* @param {string} heartMsg 心跳名称 默认字符串ping
*/
const sendPing = (heartTime: number, heartMsg: string) => {
webSocket?.send(heartMsg);
setIntervalId = setInterval(() => {
webSocket?.send(heartMsg);
}, heartTime);
};
/**
* WebSocket 关闭的回调方法
* @param config
*/
const close = (config: WebSocketProps, ev: CloseEvent) => {
config.close && config.close(ev);
clearInterval(Number(setIntervalId));
};
let falg = false;
// 重连次数
let reconnectCount = 0;
// 重连定时器id
let reconnectId: NodeJS.Timeout | null = null;
/**
* WebSocket 关闭的回调方法
* @param config
*/
const error = (config: WebSocketProps, ev: Event) => {
config.error && config.error(ev);
if (falg) return;
reconnectId = setInterval(() => {
falg = true;
reconnectCount++;
console.log("正在重新连接,次数:" + reconnectCount);
let socket = initWebSocket(config);
if (socket?.readyState === socket?.OPEN) {
reconnectCount = 0;
falg = false;
clearInterval(Number(reconnectId));
}
if (reconnectCount >= 5) {
clearInterval(Number(reconnectId));
}
}, config.reconnectTime ?? 10000);
};
2. 创建链接
新建 websocket.vue文件
下面的文件都是上面第二步用到的文件
引用到的 user 文件
import { defineStore } from "pinia";
import { UserState } from "@/stores/interface";
//UserState用到的类型如下
//export interface UserState {
token: string;
tokenName: string;
userInfo: any;
webSocket: WebSocket | null;
}
import piniaPersistConfig from "@/stores/helper/persist";
export const useUserStore = defineStore({
id: "geeker-user",
state: (): UserState => ({
token: "",
tokenName: "",
userInfo: "",
webSocket: null
}),
getters: {},
actions: {
// Set Token
setToken(token: string) {
this.token = token;
},
setTokenName(tokenName: string) {
this.tokenName = tokenName;
},
// Set setUserInfo
setUserInfo(userInfo: any) {
this.userInfo = userInfo;
},
// setWebSocket
setWebSocket(webSocket: WebSocket | null) {
this.webSocket = webSocket;
}
},
persist: piniaPersistConfig("geeker-user")
});
持久化文件 pinia
persist.ts
import { PersistedStateOptions } from "pinia-plugin-persistedstate";
/**
* @description pinia 持久化参数配置
* @param {String} key 存储到持久化的 name
* @param {Array} paths 需要持久化的 state name
* @return persist
* */
const piniaPersistConfig = (key: string, paths?: string[]) => {
const persist: PersistedStateOptions = {
key,
storage: localStorage,
// storage: sessionStorage,
paths
};
return persist;
};
export default piniaPersistConfig;
websocketUrl文件
websocketUrl.ts
/**
* 连接WebSocket服务地址的网关IP端口 -- 开发环境
* (解决扫描漏洞:IP地址泄露)
*/
// 头部
//示例"ws://199.166.0."
export const DEV_WS_URL_HEAD = "";
// 尾部
//示例"11:1111"
export const DEV_WS_URL_TAIL = "";
/**
* 连接WebSocket服务地址的网关IP端口 -- 正式环境
* (解决扫描漏洞:IP地址泄露)
*/
// 头部
//示例"ws://00.111."
export const PRO_WS_URL_HEAD = "";
// 尾部
//示例"111.11:1111"
export const PRO_WS_URL_TAIL = "";
@/api/interface/webSocketMsg/index.ts 文件如下
/**
* WebSocket 消息类型
*/
export interface WebSocketMsg {
/**
* 事件标识
**/
eventKey: EventKeyEnum | "";
/**
* 用户id
**/
userId: string;
/**
* 用户所属团队id
**/
userTeamId?: string;
/**
* 用户token
**/
token?: string;
/**
* 消息内容
*
**/
msgContent: string;
/**
* 消息发送时间(yyyy-MM-dd HH:mm:ss)
*
**/
sendTime: string;
/**
* 是否发送给所有人
*
**/
everyone: boolean;
}
export enum EventKeyEnum {
/**
* WebSocket连接成功标识,根据后台定义
*/
CONNECTION_SUCCESS = "",
/**
* 提醒消息推送
*/
MSG_COMMON = "",
/**
* 用户登录认证相关消息
*/
SATOKEN = ""
}
mitt 使用
mittBus.ts文件
import mitt from "mitt";
const mittBus = mitt();
export default mittBus;