Vue项目中WebSocket封装

WEBSOCKET

封装

utils下建立WebSocketManager.js

javascript 复制代码
class WebSocketManager {
    constructor() {
        this.url = null;
        this.websocket = null;
        this.isConnected = false;
        this.listeners = {
            onopen: [],
            onmessage: [],
            onclose: [],
            onerror: [],
        };
        this.reconnectionOptions = {
            enabled: true,
            maxAttempts: 5,
            delay: 3000,
        };
        this.reconnectionAttempts = 0;
        this.connecting = false;
        this.url = null;
        this.preventReconnect = false;
        // 添加Ping-Pong定时器
        this.pingInterval = null;
        this.websocketId = '';
    }

    initializeWebSocket(url) {
        sessionStorage.setItem('ws_url', url);
        if (
            !this.websocket ||
            this.websocket.readyState === WebSocket.CLOSED
        ) {
            const websocketId = new Date().getTime();
            this.websocketId = websocketId;
            this.websocket = new WebSocket(url);
            this.url = url;
            this.preventReconnect = false; // 重置标志位
            this.websocket.onopen = (event) => {
                if (websocketId !== this.websocketId) {
                    return
                }
                console.log('onopen', websocketId);
                this.isConnected = true;
                this.connecting = false;
                this.reconnectionAttempts = 0;
                this.fireListeners('onopen', event);
                this.websocket.send(`ping`);
                console.log('send registerEcmsServer');
                this.startPingPong();
            };

            this.websocket.onmessage = (event) => {
                if (websocketId !== this.websocketId) {
                    return
                }
                console.log('onmessage', event.data);
                try {
                    const jsonData = JSON.parse(event.data);
                    this.fireListeners('onmessage', jsonData);
                } catch (e) {
                    // console.error('onmessage-err', e);
                }
            };

            this.websocket.onclose = (event) => {
                console.log('onclose ', event);
                if (websocketId !== this.websocketId) {
                    console.log('do xxx')
                    return
                }
                this.stopPingPong();
                if (event.code !== 4000) {
                    setTimeout(() => {
                        console.log('reconnect ');
                        this.reconnect();
                    }, 2000);
                }
            };

            this.websocket.onerror = (error) => {
                if (websocketId !== this.websocketId) {
                    return
                }
                console.log('onerror ', error);
                this.fireListeners('onerror', error);
            };
        } else {
            console.log('Soeket exists, no need to create it, 链接状态:',  this.websocket.readyState === WebSocket.OPEN);
        }
    }

    close() {
        this.preventReconnect = true;
        this.reconnectionAttempts = 0;
        this.connecting = false;
        this.url = null;
        this.preventReconnect = false;
        this.isConnected = false;
        if (this.websocket) {
            this.websocket.close(4000);
        }
    }

    reconnect() {
        if (!this.url && sessionStorage.getItem('ws_url')) {
            return;
        }
        if (!this.preventReconnect && !this.connecting) {
            this.connecting = true;
            this.reconnectionAttempts++;
            setTimeout(() => {
                this.initializeWebSocket(
                    this.url
                );
            }, this.reconnectionOptions.delay);
        }
    }

    send(message) {
        if (this.websocket && this.websocket.readyState === WebSocket.OPEN) {
            this.websocket.send(message);
        }
    }

    addEventListener(eventType, callback) {
        if (this.listeners[eventType]) {
            this.listeners[eventType].push(callback);
        }
    }

    removeEventListener(eventType, callback) {
        if (this.listeners[eventType]) {
            const index = this.listeners[eventType].indexOf(callback);
            if (index !== -1) {
                this.listeners[eventType].splice(index, 1);
            }
        }
    }

    fireListeners(eventType, event) {
        this.listeners[eventType].forEach((callback) => {
            callback(event);
        });
    }
    startPingPong() {
        if (this.pingInterval) {
            clearInterval(this.pingInterval);
        }
        // 设置Ping间隔(ms)
        const pingInterval = 20 * 1000;

        this.pingInterval = setInterval(() => {
            if (
                this.websocket &&
                this.websocket.readyState === WebSocket.OPEN
            ) {
                // 发送Ping消息
                this.websocket.send(`ping`);
            }
        }, pingInterval);
    }

    stopPingPong() {
        // 停止Ping-Pong定时器
        if (this.pingInterval) {
            clearInterval(this.pingInterval);
            this.pingInterval = null;
        }
    }
}

const WebSocketManagerInstance = new WebSocketManager();

export default WebSocketManagerInstance;

引入

在main.js中引入

javascript 复制代码
import Vue from 'vue';
import Socket from '@/utils/WebSocketManager';
Vue.prototype.$socket = Socket;

初始化

javascript 复制代码
const WS= 'ws://127.0.0.1:80/ws';
this.$socket.initializeWebSocket(WS);

使用

javascript 复制代码
    mounted() {
        this.$socket.addEventListener('onmessage', this.handleWs);
    },
    beforeDestroy() {
        this.$socket.removeEventListener('onmessage', this.handleWs);
    },
    methods: {
        // 处理ws
        handleWs(e) {
            switch (e.method) {
                // 被动进入庭审
                case 'XXX':
                    console.log('xxx')
                    break;
            }
        },
    }

如有不足,请多指教,

未完待续,持续更新!

大家一起进步!

相关推荐
前端_yu小白6 分钟前
leaflet实现点位聚合
前端·javascript
Smile_Gently2 小时前
前端:最简单封装nmp插件(组件)过程。
前端·javascript·vue.js·elementui·vue
nihui1237 小时前
Uniapp 实现顶部标签页切换功能?
javascript·vue.js·uni-app
一 乐9 小时前
高校体育场管理系统系统|体育场管理系统小程序设计与实现(源码+数据库+文档)
前端·javascript·数据库·spring boot·高校体育馆系统
shengmeshi9 小时前
vue3项目img标签动态设置src,提示:ReferenceError: require is not defined
javascript·vue.js·ecmascript
BillKu9 小时前
vue3中<el-table-column>状态的显示
javascript·vue.js·elementui
祈澈菇凉9 小时前
ES6模块的异步加载是如何实现的?
前端·javascript·es6
我爱学习_zwj9 小时前
4.从零开始学会Vue--{{组件通信}}
前端·javascript·vue.js·笔记·前端框架
*TQK*10 小时前
✨1.HTML、CSS 和 JavaScript 是什么?
前端·javascript·css·html
优联前端10 小时前
DeepSeek 接入PyCharm实现AI编程!(支持本地部署DeepSeek及官方DeepSeek接入)
javascript·pycharm·ai编程·前端开发·优联前端·deepseek