uniapp利用vue3语法使用并封装WebSocket(心跳检测、断线重连)

一、代码封装

// WebSocket 工具类,封装了 WebSocket 的连接、发送、接收、心跳、重连和关闭等操作  
class WebsocketUtil {  
    // WebSocket 服务器的 URL  
    url: string;  
    // 心跳发送的间隔时间(秒)  
    time: number;  
    // WebSocket 任务对象  
    socketTask: any;  
    // WebSocket 连接是否打开  
    isOpen: boolean;  
    // 重连定时器  
    reconnectTimeout: NodeJS.Timeout | null;  
    // 心跳定时器  
    heartbeatInterval: NodeJS.Timeout | null;  
    // 存储外部注册的消息回调函数的数组  
    messageCallbacks: Array<(data: string) => void>;  
  
    // 构造函数,初始化 WebSocket 连接  
    constructor(url: string, time: number) {  
        this.url = url;  
        this.time = time;  
        this.socketTask = null;  
        this.isOpen = false;  
        this.reconnectTimeout = null;  
        this.heartbeatInterval = null;  
        this.messageCallbacks = [];  
  
        // 初始化 WebSocket 连接  
        this.initializeWebSocket();  
    }  
  
    // 初始化 WebSocket 连接  
    initializeWebSocket() {  
        this.socketTask = uni.connectSocket({  
            url: this.url,  
            success: () => {  
                console.log('WebSocket连接成功');  
                this.isOpen = true;  
                // 连接成功后启动心跳和消息监听  
                this.startHeartbeat();  
                this.listenForMessages();  
            },  
            fail: (error) => {  
                console.error('WebSocket连接失败', error);  
                this.reconnect();  
            }  
        });  
  
        // 注意:这里的 onClose 监听器应该放在 uni.connectSocket 调用之后  
        this.socketTask.onClose((result: any) => {  
            this.isOpen = false;  
            this.reconnect();  
        });  
    }  
  
    // 启动心跳检测  
    startHeartbeat() {  
        if (this.heartbeatInterval) {  
            clearInterval(this.heartbeatInterval);  
        }  
        this.heartbeatInterval = setInterval(() => {  
            if (this.isOpen) {  
                this.send('ping');  
            }  
        }, this.time * 1000);  
    }  
  
    // 发送消息  
    send(data: string) {  
        if (this.socketTask && this.isOpen) {  
            this.socketTask.send({  
                data: data,  
                success: (res: any) => {  
                    console.log('消息发送成功', res);  
                },  
                fail: (error: any) => {  
                    console.error('消息发送失败', error);  
                    this.reconnect(); // 这里可能需要根据实际情况判断是否重连  
                }  
            });  
        }  
    }  
  
    // 监听 WebSocket 消息  
    listenForMessages() {  
        if (this.socketTask) {  
            this.socketTask.onMessage((res: { data: any }) => {  
                const { data } = res;  
                this.messageCallbacks.forEach(callback => callback(data.toString())); // 假设 data 是字符串或可转换为字符串  
            });  
        } else {  
            console.error('WebSocket 连接尚未建立,无法监听消息');  
        }  
    }  
  
    // 重连 WebSocket  
    reconnect() {  
        if (this.reconnectTimeout) {  
            clearTimeout(this.reconnectTimeout);  
        }  
        this.reconnectTimeout = setTimeout(() => {  
            this.initializeWebSocket();  
        }, 3000);  
    }  
  
    // 关闭 WebSocket 连接  
    closeSocket() {  
        if (this.socketTask) {  
            uni.closeSocket({  
                success: () => {  
                    console.log('WebSocket连接已关闭');  
                    this.isOpen = false;  
                },  
                fail: (error) => {  
                    console.error('关闭WebSocket连接失败', error);  
                }  
            });  
            this.socketTask = null;  
        }  
    }  
  
    // 外部注册消息回调函数  
    onMessage(callback: (data: string) => void) {  
        this.messageCallbacks.push(callback);  
    }  
  
    // 外部注销消息回调函数  
    offMessage(callback: (data: string) => void) {  
        this.messageCallbacks = this.messageCallbacks.filter(cb => cb !== callback);  
    }  
  
    // 销毁 WebSocket 连接,清理资源  
    destroy() {  
        this.closeSocket();  
        clearInterval(this.heartbeatInterval);  
        clearTimeout(this.reconnectTimeout);  
        this.messageCallbacks = [];  
    }  
}  
  
export default WebsocketUtil;

二、单页面使用

<template>  
  <div>  
    <!-- 你的组件模板 -->  
  </div>  
</template>  
  
<script setup>  
import { ref, onUnmounted } from 'vue';  
import WebsocketUtil from './WebsocketUtil';  
  
const websocket = ref(null);  
  
// 组件挂载时初始化WebSocket  
onMounted(() => {  
  websocket.value = new WebsocketUtil('wss://your-websocket-url.com', 5);  
  
  // 可以注册消息回调  
  websocket.value.onMessage(data => {  
    console.log('Received data:', data);  
  });  
});  
  
// 组件卸载时清理WebSocket  
onUnmounted(() => {  
  if (websocket.value) {  
    websocket.value.destroy();  
  }  
});  
</script>

二、全局使用

方法一、

1.在app.vue中

<template>  
  <div id="app">  
    <!-- 子组件 -->  
  </div>  
</template>  
  
<script setup>  
import { provide } from 'vue';  
import WebsocketUtil from './path/to/WebsocketUtil';  
  
const websocketUtil = new WebsocketUtil('your-websocket-url', 5); // 创建 WebSocket 工具类实例  
provide('websocketUtil', websocketUtil); // 提供给所有子组件  
</script>

2.页面上调用

<script setup>  
import { inject } from 'vue';  
  
const websocketUtil = inject('websocketUtil'); // 注入 WebSocket 工具类实例  
  
// 现在你可以使用 websocketUtil 来进行 WebSocket 通信了  
websocketUtil.onMessage(data => {  
  console.log('Received data:', data);  
});  
</script>

方法二

在main.js中

//引入websocket文件
import wsRequest from './websocket.js'
//开启websocket
let websocket = new wsRequest("ws://xxx:you.are.url/connect/websocket",50)
//挂载到全局
Vue.prototype.$socket = websocket

方法三 vuex或者pinia

对于更复杂的状态管理,特别是当 WebSocket 的状态需要在多个组件之间共享时,使用 Vuex 或 Pinia 可能是更好的选择。你可以在这些状态管理库中创建一个模块来专门处理 WebSocket 连接和消息,大致的原理同上。

猜你喜欢

转载自blog.csdn.net/weixin_48642777/article/details/141818710