vue3单页面连接多个websocket并实现断线重连功能
需求:需要在单页面中创建多个websocket并且互不影响,并实现断线重连机制,在网上看了很多文章,也下了几个插件,最后实现,在这里我不推荐使用vue-native-websocket-vue3,我看官方文档和案例,没看到怎么连接多个的,所以放弃了,socket.io-client也试过了,是需要后端要下载socket.io?放弃了,最后实现如下要求:
- vue3+pinia实现封装websocket
- 单页面可调用多个websocke连接并互不影响
- 设置重连机制,并设置最大重连数
1.效果
1.1设置断线重连(设置最大重连数为5),效果如下
1.2发送消息
1.3连接多个
2.完整代码
2.1封装websocke
// stores/websocketStore.js
import { defineStore } from 'pinia'export const useWebSocketStore = defineStore('websocket', {state: () => ({connections: {},defaultReconnectAttempts: 3,//默认最大重连次数defaultReconnectInterval: 5000,//重连间隔}),actions: {// 连接connect({ key, url, onMessage, options = {} }) {// 如果已存在相同key的连接,先关闭if (this.connections[key]) {this.disconnect(key)}const reconnectAttempts = options.reconnectAttempts ?? this.defaultReconnectAttemptsconst reconnectInterval = options.reconnectInterval ?? this.defaultReconnectIntervalconst connection = {instance: null,url,onMessage,options,reconnectCount: 0, // 当前重连次数maxReconnectAttempts: reconnectAttempts,reconnectInterval,reconnectTimer: null}this.createWebSocket(key, connection)this.connections[key] = connection},// 创建WebSocket实例(用于初始连接和重连)createWebSocket(key, connection) {connection.instance = new WebSocket(connection.url)connection.instance.onopen = () => {console.log(`WebSocket ${key} connected`)connection.reconnectCount = 0 // 重置重连计数器}connection.instance.onmessage = (event) => {if (typeof connection.onMessage === 'function') {connection.onMessage(event.data)}}connection.instance.onclose = (event) => {if (event.wasClean) {console.log(`WebSocket ${key} closed cleanly`)} else {this.handleReconnect(key)}}connection.instance.onerror = (error) => {console.error(`WebSocket ${key} error:`, error)connection.instance.close() // 触发onclose}},// 处理重连handleReconnect(key) {const connection = this.connections[key]if (!connection) returnif (connection.reconnectCount < connection.maxReconnectAttempts) {connection.reconnectCount++// 尝试重新连接日志console.log(`Attempting to reconnect ${key} (${connection.reconnectCount}/${connection.maxReconnectAttempts})`)connection.reconnectTimer = setTimeout(() => {if (connection.instance) {connection.instance.close()connection.instance = null}// 重新创建WebSocket实例而不重置计数器this.createWebSocket(key, connection)}, connection.reconnectInterval)} else {// 最大重连尝试次数 reachedconsole.log(`Max reconnection attempts (${connection.maxReconnectAttempts}) reached for ${key}`)}},// 关闭单个连接disconnect(key) {if (this.connections[key]) {const connection = this.connections[key]if (connection.instance) {connection.instance.close()}if (connection.reconnectTimer) {clearTimeout(connection.reconnectTimer)}delete this.connections[key]console.log(`WebSocket ${key} disconnected`)}},// 发送消息send(key, data) {const connection = this.connections[key]if (connection?.instance?.readyState === WebSocket.OPEN) {connection.instance.send(JSON.stringify(data))} else {console.error(`WebSocket ${key} is not connected`)}},// 关闭所有连接disconnectAll() {Object.keys(this.connections).forEach(key => {this.disconnect(key)})}}
})
2.2页面调用
调用多个websocke连接
import { useWebSocketStore } from "@/stores/websocketStore.js";// // 获取store
const websocketStore = useWebSocketStore();
const messages1 = ref([]);
const messages2 = ref([]);
const connectSocket1 = () => {websocketStore.connect({key: "socket1",url: "wss://aa.websocket.bb", // 测试用的WebSocket服务onMessage: (data) => {messages1.value.push(data);console.log("Socket1 received:", data);},options: {reconnectAttempts: 5, // 自定义重试次数reconnectInterval: 3000, // 自定义重试间隔},});
};const connectSocket2 = () => {websocketStore.connect({key: "socket2",url: "wss://bb.websocket.cc", // 另一个WebSocket服务onMessage: (data) => {messages2.value.push(data);console.log("Socket2 连接状态:", data);},});
};
// 生命周期钩子
onMounted(() => {connectSocket1();connectSocket2();
});
2.3断开所有连接
const disconnectAll = () => {websocketStore.disconnectAll();
};
// 组件卸载时断开所有连接
onUnmounted(() => {disconnectAll();
});
2.4断开单个连接
const disconnectSocket1 = () => {websocketStore.disconnect("socket1");
};
2.5发送消息
const sendDataWebsocket = () => {websocketStore.send("socket1", "Hello, World!");
};
文章到此结束,希望对你有所帮助~