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 连接和消息,大致的原理同上。

以下是一个示例代码,实现了Uniapp封装WebSocket的功能,包括重连和心跳功能,并可以在全局使用。 ```javascript // utils/websocket.js const HEARTBEAT_TIME = 30 * 1000 // 心跳时间间隔 class WebSocketUtil { constructor(url, options = {}) { this.url = url this.options = options this.socket = null this.isReconnecting = false // 是否正在重连 this.heartbeatInterval = null // 心跳定时器 } connect() { return new Promise((resolve, reject) => { this.socket = uni.connectSocket({ url: this.url, ...this.options, success: () => { this.initEvent() resolve() }, fail: reject, }) }) } initEvent() { this.socket.onOpen(() => { console.log('WebSocket连接已打开') this.startHeartbeat() // 开始心跳 }) this.socket.onClose((e) => { console.log('WebSocket连接已关闭', e) this.stopHeartbeat() // 停止心跳 if (!this.isReconnecting) { this.isReconnecting = true this.reconnect() // 重连 } }) this.socket.onError((e) => { console.log('WebSocket连接发生错误', e) this.stopHeartbeat() // 停止心跳 if (!this.isReconnecting) { this.isReconnecting = true this.reconnect() // 重连 } }) this.socket.onMessage((res) => { console.log('WebSocket收到消息', res) }) } reconnect() { setTimeout(() => { console.log('WebSocket正在重连...') this.connect().then(() => { console.log('WebSocket重连成功') this.isReconnecting = false }).catch(() => { console.log('WebSocket重连失败') this.reconnect() }) }, 3000) } startHeartbeat() { this.heartbeatInterval = setInterval(() => { if (this.socket.readyState === 1) { console.log('WebSocket发送心跳') this.socket.send({ type: 'heartbeat' }) } }, HEARTBEAT_TIME) } stopHeartbeat() { clearInterval(this.heartbeatInterval) } } export default { install(Vue) { const websocket = new WebSocketUtil('wss://example.com') Vue.prototype.$websocket = websocket websocket.connect() }, } ``` 使用时,在main.js中引入并注册即可: ```javascript // main.js import Vue from 'vue' import App from './App.vue' import websocket from './utils/websocket' Vue.config.productionTip = false Vue.use(websocket) new Vue({ render: h => h(App), }).$mount('#app') ``` 在组件中,可以通过`this.$websocket`来获取WebSocket实例,然后进行发送消息等操作: ```javascript // HelloWorld.vue export default { mounted() { this.$websocket.socket.send({ type: 'hello' }) } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值