|
|
/* * @description: 封装socket方法 * @date: 2023-01-20 * @author: 郭安鹏 */ import { ElMessage } from 'element-plus' import { ref } from 'vue'
export const isClose = ref(true)
interface socket { appKey: any websocket: any connectURL: string socket_open: boolean hearBeat_timer: any hearBeat_interval: number is_reconnect: boolean reconnect_count: number reconnect_current: number reconnect_number: number reconnect_timer: any reconnect_interval: number receiveMessageCallBackObj: any initCallBacks: any // eslint-disable-next-line ts/no-unsafe-function-type
receiveMessage: Function // eslint-disable-next-line ts/no-unsafe-function-type
registerCallback: Function // eslint-disable-next-line ts/no-unsafe-function-type
registerInitCallback: Function // eslint-disable-next-line ts/no-unsafe-function-type
init: (receiveMessage?: Function | null, type?: string, connectURL?: string) => any heartbeat: () => void heartSend: () => void send: (data: any, callback?: any) => void close: () => void reconnect: () => void sendAppJoin: () => void }
// eslint-disable-next-line ts/no-redeclare
export const socket: socket = { appKey: null, websocket: null, connectURL: import.meta.env.FT_WS_URL, // 开启标识
socket_open: false, // 心跳timer
hearBeat_timer: null, // 心跳发送频率
hearBeat_interval: 500, // 是否需要重连
is_reconnect: true, // 重连次数
reconnect_count: 10, // 已发起重连次数
reconnect_current: 1, // 网络错误提示此时
reconnect_number: 0, // 重连timer
reconnect_timer: null, // 重连频率
reconnect_interval: 1000,
receiveMessageCallBackObj: {}, initCallBacks: [], // eslint-disable-next-line ts/no-unsafe-function-type
registerInitCallback: (fn: Function, ...args: any) => { // socket 连接成功后的回调
socket.initCallBacks.push({ fn, args, }) }, // 接收消息的方法
receiveMessage: (e: any) => { const message = JSON.parse(e.data) const fn = socket.receiveMessageCallBackObj[message.type] if (fn) { fn(message) } else { console.error('请注册当前类型的回调函数', message) } }, registerCallback: (fn: any, type: any) => { // 接收消息的回调
socket.receiveMessageCallBackObj[type] = fn },
init: async ( receiveMessageCallBack: any, type?: string, connectURL?: string, reconnection?: boolean, ) => { if (!('WebSocket' in window)) { ElMessage.warning('浏览器不支持WebSocket') return null }
// 注册回调函数
if (receiveMessageCallBack && type) { socket.registerCallback(receiveMessageCallBack, type) } // 已经创建过连接无需重复创建
if (socket.websocket && !reconnection) { return socket.websocket }
await new Promise((rs) => { socket.websocket = new WebSocket(connectURL || socket.connectURL) // 消息接收
socket.websocket.onmessage = (e: any) => { socket.receiveMessage(e) } // socket关闭
socket.websocket.onclose = () => { console.error('onclose')
clearInterval(socket.hearBeat_interval) socket.socket_open = false isClose.value = true // 需要重新连接
if (socket.is_reconnect) { socket.reconnect_timer = setTimeout(() => { // 超过重连次数
// if (socket.reconnect_current > socket.reconnect_count) {
// clearTimeout(socket.reconnect_timer);
// socket.is_reconnect = false;
// console.error('超出重连次数,不再重连', new Date());
// return;
// }
// 记录重连次数
socket.reconnect_current++ socket.reconnect() }, socket.reconnect_interval) } } // 连接发生错误
socket.websocket.onerror = function () { console.error('onerror') isClose.value = true socket.socket_open = false } // 连接成功
socket.websocket.onopen = function () { socket.socket_open = true socket.is_reconnect = true // 开启心跳
socket.heartbeat() // 连接成功后发起app加入消息
socket.sendAppJoin()
for (const fnItem of socket.initCallBacks) { fnItem.fn(...fnItem.args) }
isClose.value = false
rs(true) // socket 已连接
} }) },
send: (data, callback = null) => { // 开启状态直接发送
if (socket.websocket.readyState === socket.websocket.OPEN) { socket.websocket.send(JSON.stringify(data)) if (callback) { callback() } } else { clearInterval(socket.hearBeat_timer) socket.reconnect_number++ } },
heartbeat: () => { if (socket.hearBeat_timer) { clearInterval(socket.hearBeat_timer) } socket.hearBeat_timer = setInterval(() => { socket.heartSend() }, socket.hearBeat_interval) }, heartSend: () => { socket.send({ type: 'ping', // ping
}) }, close: () => { clearInterval(socket.hearBeat_timer) socket.is_reconnect = false socket.websocket && socket.websocket.close() socket.websocket = null },
/** * 重新连接 */ reconnect: () => { if (socket.websocket) { // 需要重连
if (socket.is_reconnect) { socket.websocket.close() socket.websocket = null socket.init() } else { socket.close() } } },
sendAppJoin: () => { socket.send({ appKey: socket.appKey, type: 1, // appJoin
}) }, }
|