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

如有不足,请多指教,

未完待续,持续更新!

大家一起进步!

相关推荐
Java后端的Ai之路2 小时前
CAS并发控制-从CPU指令到企业级乐观锁
vue.js·人工智能·python·cas·乐观锁
Da Da 泓3 小时前
五子棋 Web 端测试用例报告
前端·网络·websocket·网络协议·测试用例·项目
程序员大阳4 小时前
副队长JavaScript教程(50)-DOM:网页开发的起点
javascript·dom·es·节点·概念·document·关系
香芋芋圆9 小时前
iD-editor 详解|OSM官方在线编辑器,基于D3.js的轻量地图编辑器
开发语言·javascript·编辑器
晗夜未央11 小时前
任务队列反复失败,先分清重试、阻塞和结果待核对
开发语言·javascript
jktantan11 小时前
每个节点 41 字节:把一棵百万节点树拆进 14 个 typed array
前端·javascript·vue.js·算法·typescript
我命由我1234512 小时前
访客系统形式(有用户概念、无用户概念)
java·开发语言·前端·javascript·python·产品运营·产品经理
程序员大阳13 小时前
副队长JavaScript教程(65)-详解JSON:轻量级数据交换格式
javascript·json·序列化·反序列化·stringify·parse
小大宇14 小时前
Vue知识点-ElementPlus-06 单选+多选+下拉+日期选择
前端·vue.js·elementui
paopaokaka_luck14 小时前
基于springboot+vue的益暖微光公益服务平台(DeepSeek公益助手、善款信息追溯、志愿服务积分闭环、ECharts运营分析、活动状态自动流转)
java·前端·javascript·spring boot·mysql·架构·echarts