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

如有不足,请多指教,

未完待续,持续更新!

大家一起进步!

相关推荐
雨落Re35 分钟前
从递归组件到 DSL 引擎:我造了一个让 AI 能"搭 UI"的运行时
前端·vue.js
Maxkim36 分钟前
前端工程化落地指南:pnpm workspace + Monorepo 核心用法与实践
前端·javascript·架构
小兵张健13 小时前
开源 playwright-pool 会话池来了
前端·javascript·github
codingWhat16 小时前
介绍一个手势识别库——AlloyFinger
前端·javascript·vue.js
Lee川16 小时前
深度拆解:基于面向对象思维的“就地编辑”组件全模块解析
javascript·架构
进击的尘埃16 小时前
Web Worker 与 OffscreenCanvas:把主线程从重活里解放出来
javascript
踩着两条虫16 小时前
VTJ.PRO 双向代码转换原理揭秘
前端·vue.js·人工智能
codingWhat16 小时前
手撸一个「能打」的 React Table 组件
前端·javascript·react.js
进击的尘埃16 小时前
用 TypeScript 的 infer 搓一个类型安全的深层路径访问工具
javascript
yuki_uix16 小时前
Object.entries:优雅处理 Object 的瑞士军刀
前端·javascript