需求:需要在单页面中创建多个websocket并且互不影响,并实现断线重连机制,在网上看了很多文章,也下了几个插件,最后实现,在这里我不推荐使用vue-native-websocket-vue3,我看官方文档和案例,没看到怎么连接多个的,所以放弃了,socket.io-client也试过了,是需要后端要下载socket.io?放弃了,最后实现如下要求:

  1. vue3+pinia实现封装websocket
  2. 单页面可调用多个websocke连接并互不影响
  3. 设置重连机制,并设置最大重连数

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.defaultReconnectAttempts
            const reconnectInterval = options.reconnectInterval ?? this.defaultReconnectInterval

            const 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) return

            if (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 {
                // 最大重连尝试次数 reached
                console.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!");
};

文章到此结束,希望对你有所帮助~

 

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐