feat: ws 封装工具测试
This commit is contained in:
@@ -1,13 +1,19 @@
|
||||
import { sessionGet } from "@/utils/cache-session-utils";
|
||||
import { sessionGet } from '@/utils/cache-session-utils';
|
||||
import { getToken } from './auth-token';
|
||||
import { localGet } from '@/utils/cache-local-utils';
|
||||
import { CACHE_LOCAL_I18N } from '@/constants/cache-keys-constants';
|
||||
import { TOKEN_RESPONSE_FIELD } from '@/constants/token-constants';
|
||||
|
||||
/**连接参数类型 */
|
||||
export type TypeParams = {
|
||||
export type OptionsType = {
|
||||
/**WebSocket服务器将响应的URL */
|
||||
url?: string;
|
||||
/**地址栏参数 */
|
||||
params?: Record<string, string | number | boolean | undefined>;
|
||||
/**onopen事件的回调函数 */
|
||||
onopen?: Function;
|
||||
/**message事件的回调函数 */
|
||||
onmessage: Function;
|
||||
onmessage: (data: Record<string, any>) => void;
|
||||
/**error事件的回调函数 */
|
||||
onerror: Function;
|
||||
/**close事件的回调函数 */
|
||||
@@ -41,7 +47,7 @@ export class WS {
|
||||
/**ws 实例 */
|
||||
private ws: WebSocket | null = null;
|
||||
/**ws 连接参数 */
|
||||
private params: TypeParams | null = null;
|
||||
private options: OptionsType | null = null;
|
||||
/**心跳调度器 */
|
||||
private heartInterval: number = 0;
|
||||
/**重连定时器 */
|
||||
@@ -51,87 +57,135 @@ export class WS {
|
||||
* 构造函数
|
||||
* @param {object} params 构造函数参数
|
||||
*/
|
||||
constructor(params: TypeParams) {
|
||||
constructor(options: OptionsType) {
|
||||
if (!window.WebSocket) {
|
||||
// 检测浏览器支持
|
||||
console.error('抱歉! 浏览器不支持websocket');
|
||||
return;
|
||||
}
|
||||
this.params = params;
|
||||
this.create(params);
|
||||
this.options = options;
|
||||
this.create(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建链接
|
||||
* @param {object} params 连接参数
|
||||
* @param {object} options 连接参数
|
||||
*/
|
||||
public create(params: TypeParams) {
|
||||
public create(options: OptionsType) {
|
||||
try {
|
||||
if (!params.url) {
|
||||
if (!options.url) {
|
||||
// 兼容旧前端可改配置文件
|
||||
const baseUrl = import.meta.env.PROD
|
||||
const wsUrl = import.meta.env.PROD
|
||||
? sessionGet('wsUrl') || import.meta.env.VITE_API_BASE_URL
|
||||
: import.meta.env.VITE_API_BASE_URL;
|
||||
params.url = `ws://${baseUrl}/ws`;
|
||||
: '/socket';
|
||||
if (wsUrl.startsWith('ws')) {
|
||||
options.url = `${wsUrl}/ws`;
|
||||
} else if (wsUrl.startsWith('https')) {
|
||||
options.url = `${wsUrl.replace('https', 'wss')}/ws`;
|
||||
} else if (wsUrl.startsWith('http')) {
|
||||
options.url = `${wsUrl.replace('http', 'ws')}/ws`;
|
||||
} else {
|
||||
const protocol =
|
||||
window.location.protocol === 'https:' ? 'wss://' : 'ws://';
|
||||
options.url = `${protocol}${location.host}${wsUrl}/ws`;
|
||||
}
|
||||
|
||||
const ws = new WebSocket(params.url);
|
||||
// 地址栏参数
|
||||
let params = options.params || {};
|
||||
// 设置 token
|
||||
const token = getToken();
|
||||
if (token) {
|
||||
params[TOKEN_RESPONSE_FIELD] = token;
|
||||
}
|
||||
// 多语言处理
|
||||
params['language'] = localGet(CACHE_LOCAL_I18N) || 'en_US';
|
||||
let paramStr = '';
|
||||
for (const key in params) {
|
||||
const value = params[key];
|
||||
// 空字符或未定义的值不作为参数发送
|
||||
if (value === '' || value === undefined) continue;
|
||||
paramStr += `&${encodeURIComponent(key)}=${encodeURIComponent(
|
||||
value
|
||||
)}`;
|
||||
}
|
||||
if (paramStr && paramStr.startsWith('&')) {
|
||||
options.url = `${options.url}?${paramStr.substring(1)}`;
|
||||
}
|
||||
}
|
||||
|
||||
const ws = new WebSocket(options.url, 'omc-ws');
|
||||
// 用于指定连接成功后的回调函数。
|
||||
ws.onopen = ev => {
|
||||
if (params.heartTimer && params.heartTimer > 0) {
|
||||
this.heartCheck(params.heartTimer);
|
||||
if (options.heartTimer && options.heartTimer > 0) {
|
||||
this.heartCheck(options.heartTimer);
|
||||
}
|
||||
if (typeof params.onopen === 'function') {
|
||||
params.onopen(ev);
|
||||
if (typeof options.onopen === 'function') {
|
||||
options.onopen(ev);
|
||||
}
|
||||
};
|
||||
// 用于指定当从服务器接受到信息时的回调函数。
|
||||
ws.onmessage = ev => {
|
||||
if (typeof params.onmessage === 'function') {
|
||||
params.onmessage(ev);
|
||||
const data = ev.data;
|
||||
// 解析文本消息
|
||||
if (ev.type === 'message') {
|
||||
try {
|
||||
const jsonData = JSON.parse(data);
|
||||
if (typeof options.onmessage === 'function') {
|
||||
options.onmessage(jsonData);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('websocket 消息格式错误', error);
|
||||
}
|
||||
}
|
||||
};
|
||||
// 用于指定连接关闭后的回调函数。
|
||||
ws.onclose = ev => {
|
||||
if (typeof params.onclose === 'function') {
|
||||
params.onclose(ev);
|
||||
if (typeof options.onclose === 'function') {
|
||||
options.onclose(ev);
|
||||
}
|
||||
};
|
||||
// 用于指定连接失败后的回调函数。
|
||||
ws.onerror = ev => {
|
||||
console.error('websocket 连接异常', ev);
|
||||
|
||||
if (typeof params.onerror === 'function') {
|
||||
params.onerror(ev);
|
||||
if (typeof options.onerror === 'function') {
|
||||
options.onerror(ev);
|
||||
}
|
||||
if (params.reconnectTimer && params.reconnectTimer > 0) {
|
||||
this.reconnect(params.reconnectTimer);
|
||||
if (options.reconnectTimer && options.reconnectTimer > 0) {
|
||||
this.reconnect(options.reconnectTimer);
|
||||
}
|
||||
};
|
||||
this.ws = ws;
|
||||
} catch (error) {
|
||||
if (typeof params.onerror === 'function') {
|
||||
params.onerror(error);
|
||||
if (typeof options.onerror === 'function') {
|
||||
options.onerror(error);
|
||||
}
|
||||
if (params.reconnectTimer && params.reconnectTimer > 0) {
|
||||
this.reconnect(params.reconnectTimer);
|
||||
if (options.reconnectTimer && options.reconnectTimer > 0) {
|
||||
this.reconnect(options.reconnectTimer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 发送消息
|
||||
send(data: Record<string, any>) {
|
||||
public send(data: Record<string, any>) {
|
||||
if (!this.ws) {
|
||||
console.warn('websocket 不可用');
|
||||
return;
|
||||
}
|
||||
console.log(' readyState', this.ws.readyState);
|
||||
if (
|
||||
this.ws.readyState === WebSocket.CLOSED ||
|
||||
this.ws.readyState === WebSocket.CLOSING
|
||||
) {
|
||||
this.close();
|
||||
return;
|
||||
}
|
||||
|
||||
this.ws.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
// 手动关闭socket
|
||||
close() {
|
||||
public close() {
|
||||
this.heartInterval && clearInterval(this.heartInterval);
|
||||
this.reconnectTimeout && clearTimeout(this.reconnectTimeout);
|
||||
if (!this.ws) {
|
||||
@@ -142,7 +196,7 @@ export class WS {
|
||||
}
|
||||
|
||||
// 周期性发送ping 保活
|
||||
heartCheck(heartTimer: number) {
|
||||
private heartCheck(heartTimer: number) {
|
||||
this.heartInterval = window.setInterval(() => {
|
||||
this.send({
|
||||
type: 'ping',
|
||||
@@ -151,12 +205,12 @@ export class WS {
|
||||
}
|
||||
|
||||
// 断线重连
|
||||
reconnect(reconnectTimer: number) {
|
||||
private reconnect(reconnectTimer: number) {
|
||||
if (this.reconnectTimeout > 0) return;
|
||||
clearTimeout(this.reconnectTimeout);
|
||||
this.reconnectTimeout = window.setTimeout(() => {
|
||||
if (this.params) {
|
||||
this.create(this.params);
|
||||
if (this.options) {
|
||||
this.create(this.options);
|
||||
this.reconnectTimeout = 0;
|
||||
}
|
||||
}, reconnectTimer);
|
||||
|
||||
@@ -13,10 +13,29 @@ import { ColumnsType } from 'ant-design-vue/lib/table/Table';
|
||||
import { message } from 'ant-design-vue/lib';
|
||||
import { hasPermissions } from '@/plugins/auth-user';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { WS, OptionsType } from '@/plugins/ws-websocket';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
const { t } = useI18n();
|
||||
|
||||
onMounted(() => {});
|
||||
onMounted(() => {
|
||||
const options: OptionsType = {
|
||||
params: {
|
||||
subGroupID: '1005',
|
||||
},
|
||||
onmessage: ev => {
|
||||
// 接收数据后回调
|
||||
console.log(ev);
|
||||
},
|
||||
onerror: (ev: any) => {
|
||||
// 接收数据后回调
|
||||
console.log(ev);
|
||||
},
|
||||
// 保活周期 10s
|
||||
heartTimer: 0,
|
||||
// 断线重连
|
||||
reconnectTimer: 0,
|
||||
};
|
||||
const ws = new WS(options);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -25,6 +25,13 @@ export default defineConfig(({ mode }) => {
|
||||
changeOrigin: true,
|
||||
rewrite: p => p.replace(env.VITE_API_BASE_URL, ''),
|
||||
},
|
||||
// 代理 websockets
|
||||
'/socket': {
|
||||
target: 'ws://192.168.5.58:3040',
|
||||
changeOrigin: true,
|
||||
rewrite: p => p.replace('/socket', ''),
|
||||
ws: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
resolve: {
|
||||
|
||||
Reference in New Issue
Block a user