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;
            }
        },
    }

如有不足,请多指教,

未完待续,持续更新!

大家一起进步!

相关推荐
Martin -Tang2 小时前
Vue 3 中,ref 和 reactive的区别
前端·javascript·vue.js
FakeOccupational3 小时前
nodejs 020: React语法规则 props和state
前端·javascript·react.js
放逐者-保持本心,方可放逐3 小时前
react 组件应用
开发语言·前端·javascript·react.js·前端框架
曹天骄4 小时前
next中服务端组件共享接口数据
前端·javascript·react.js
郝晨妤6 小时前
鸿蒙ArkTS和TS有什么区别?
前端·javascript·typescript·鸿蒙
AvatarGiser6 小时前
《ElementPlus 与 ElementUI 差异集合》Icon 图标 More 差异说明
前端·vue.js·elementui
喝旺仔la6 小时前
vue的样式知识点
前端·javascript·vue.js
别忘了微笑_cuicui6 小时前
elementUI中2个日期组件实现开始时间、结束时间(禁用日期面板、控制开始时间不能超过结束时间的时分秒)实现方案
前端·javascript·elementui
尝尝你的优乐美6 小时前
vue3.0中h函数的简单使用
前端·javascript·vue.js
windy1a7 小时前
【C语言】js写一个冒泡顺序
javascript