1 line
7.1 KiB
Plaintext
1 line
7.1 KiB
Plaintext
|
{"version":3,"file":"useWebSocket.js","sources":["../../../../../src/sheep/hooks/useWebSocket.js"],"sourcesContent":["import { onBeforeUnmount, reactive, ref } from 'vue'\r\nimport { baseUrl, websocketPath } from '@/sheep/config'\r\nimport { copyValueToTarget } from '@/sheep/util'\r\n\r\n/**\r\n * WebSocket 创建 hook\r\n * @param opt 连接配置\r\n * @return {{options: *}}\r\n */\r\nexport function useWebSocket(opt) {\r\n const getAccessToken = () => {\r\n return uni.getStorageSync('token')\r\n }\r\n\r\n const options = reactive({\r\n url: (baseUrl + websocketPath).replace('http', 'ws') + '?token=' + getAccessToken(), // ws 地址\r\n isReconnecting: false, // 正在重新连接\r\n reconnectInterval: 3000, // 重连间隔,单位毫秒\r\n heartBeatInterval: 5000, // 心跳间隔,单位毫秒\r\n pingTimeoutDuration: 1000, // 超过这个时间,后端没有返回pong,则判定后端断线了。\r\n heartBeatTimer: null, // 心跳计时器\r\n destroy: false, // 是否销毁\r\n pingTimeout: null, // 心跳检测定时器\r\n reconnectTimeout: null, // 重连定时器ID的属性\r\n onConnected: () => {}, // 连接成功时触发\r\n onClosed: () => {}, // 连接关闭时触发\r\n onMessage: (data) => {}, // 收到消息\r\n })\r\n const SocketTask = ref(null) // SocketTask 由 uni.connectSocket() 接口创建\r\n\r\n const initEventListeners = () => {\r\n // 监听 WebSocket 连接打开事件\r\n SocketTask.value.onOpen(() => {\r\n console.log('WebSocket 连接成功')\r\n // 连接成功时触发\r\n options.onConnected()\r\n // 开启心跳检查\r\n startHeartBeat()\r\n })\r\n // 监听 WebSocket 接受到服务器的消息事件\r\n SocketTask.value.onMessage((res) => {\r\n try {\r\n if (res.data === 'pong') {\r\n // 收到心跳重置心跳超时检查\r\n resetPingTimeout()\r\n } else {\r\n options.onMessage(JSON.parse(res.data))\r\n }\r\n } catch (error) {\r\n console.error(error)\r\n }\r\n })\r\n // 监听 WebSocket 连接关闭事件\r\n SocketTask.value.onClose((event) => {\r\n // 情况一:实例销毁\r\n if (options.destroy) {\r\n options.onClosed()\r\n } else {\r\n // 情况二:连接失败重连\r\n // 停止心跳检查\r\n stopHeartBeat()\r\n // 重连\r\n reconnect()\r\n }\r\n })\r\n }\r\n\r\n // 发送消息\r\n const sendMessage = (message) => {\r\n if (SocketTask.value && !options.destroy) {\r\n SocketTask.value.send({ data: message })\r\n }\r\n }\r\n // 开始心跳检查\r\n const startHeartBeat = () => {\r\n options.heartBeatTimer = setInterval(() => {\r\n sendMessage('ping')\r\n options.pingTimeout = setTimeout(() => {\r\n // 如果在超时时间内没有收到 pong,则认为连接断开\r\n reconnect()\r\n }, options.pingTimeoutDuration)\r\n }, options.heartBeatInterval)\r\n }\r\n // 停止心跳检查\r\n const stopHeartBeat = () => {\r\n clearInterval(options.heartBeatTimer)\r\n resetPingTimeout()\r\n }\r\n\r\n // WebSocket 重连\r\n const reconnect = () => {\r\n if (options.destroy || !SocketTask.value) {\r\n // 如果WebSocket已被销毁或尚未完全关闭,不进行重连\r\n return\r\n }\r\n\r\n // 重连中\r\n options.isReconnecting = true\r\n\r\n // 清除现有的重连标志,以避免多次重连\r\n if (options.reconnectTimeout) {\r\n clearTimeout(options.reconnectTimeout)\r\n }\r\n\r\n // 设置重连延迟\r\n options.reconnectTimeout = setTimeout(() => {\r\n // 检查组件是否仍在运行和WebSocket是否关闭\r\n if (!options.destroy) {\r\n // 重置重连标志\r\n options.isReconnecting = false\r\n // 初始化新的WebSocket连接\r\n initSocket()\r\n }\r\n }, options.reconnectInterval)\r\n }\r\n\r\n const resetPingTimeout = () => {\r\n if (options.pingTimeout) {\r
|