前端封装websocket类,实现消息注册和全局回调

实现消息注册和回调函数,实现全局使用同一个webscoket对象,并实现断线重连和心跳连接等功能,可以实现全局使用唯一实例,可以另外进行拓展配置

javascript 复制代码
// WebSocket类对象
class WebSocketCli {
    // 构造函数
    constructor(url: string, opts = {}) {
        this.url = url
        this.ws = null
        this.opts = {
            heartbeatInterval: 30000, // 默认30秒
            reconnectInterval: 5000, // 默认5秒
            maxReconnectAttempts: 5, // 默认尝试重连5次
            ...opts,
        }
        this.heartbeatInterval = 30000
        this.reconnectAttempts = 0
        this.listeners = {}
        this.init()
    }

    // 链接地址
    url: string
    // websocket实例
    ws: WebSocket | null
    // websocket配置:配置心跳和重连等信息
    opts: any
    // 重新连接次数:默认5次
    reconnectAttempts: number
    // 时间监听对象数组:可以为一个事件绑定多个监听事件
    listeners: any
    // 心跳链接间隔
    heartbeatInterval: number | null

    // 初始化ws对象
    init() {
        this.ws = new WebSocket(this.url)
        this.ws.onopen = this.onOpen.bind(this)
        this.ws.onmessage = this.onMessage.bind(this)
        this.ws.onerror = this.onError.bind(this)
        this.ws.onclose = this.onClose.bind(this)
    }

    // websocket链接建立
    onOpen(event) {
        console.log('WebSocket opened:', event)
        this.reconnectAttempts = 0 // 重置重连次数
        // 发送心跳链接
        // this.startHeartbeat()
        this.emit('open', event)
    }

    // websocket收到消息
    onMessage(event) {
        console.log('WebSocket message received:', event.data)
        this.emit('message', event.data)
    }

    // websocket错误
    onError(event) {
        console.error('WebSocket error:', event)
        this.emit('error', event)
    }

    // websocket关闭
    onClose(event) {
        console.log('WebSocket closed:', event)
        // 停止心跳链接
        // this.stopHeartbeat()
        this.emit('close', event)
        // 最大5次重连
        if (this.reconnectAttempts < this.opts.maxReconnectAttempts) {
            setTimeout(() => {
                this.reconnectAttempts++
                this.init()
            }, this.opts.reconnectInterval)
        }
    }

    // 发送心跳
    startHeartbeat() {
        this.heartbeatInterval = setInterval(() => {
            if (this.ws?.readyState === WebSocket.OPEN) {
                this.ws.send('ping') // 可以修改为你的心跳消息格式
            }
        }, this.opts.heartbeatInterval)
    }

    // 停止心跳
    stopHeartbeat() {
        if (this.heartbeatInterval) {
            clearInterval(this.heartbeatInterval)
            this.heartbeatInterval = null
        }
    }

    // 发送消息
    send(data) {
        if (this.ws?.readyState === WebSocket.OPEN) {
            this.ws.send(data)
        } else {
            console.error('WebSocket is not open. Cannot send:', data)
        }
    }

    // 注册某个消息事件,并添加回调函数
    on(event, callback) {
        if (!this.listeners[event]) {
            this.listeners[event] = []
        }
        // 将回调函数放进事件数组中
        this.listeners[event].push(callback)
    }

    // 取消某个消息:如果存在回调函数就只移除这个回调事件,不存在就清空所有
    off(event, callback?) {
        if (!this.listeners[event]) return
        const index = callback && this.listeners[event].indexOf(callback)
        if (callback && index !== -1) {
            this.listeners[event].splice(index, 1)
        } else {
            console.log('移除所有事件: ', event)
            this.listeners[event] = []
        }
    }

    // 接收到消息后,通过这个函数执行所有回调函数
    emit(event, data) {
        if (this.listeners[event]) {
            this.listeners[event].forEach((callback) => callback(data))
        }
    }
}

// 导出对象
export default WebSocketCli

使用的时候:单例模式

复制代码
// 全局唯一websocket对象
const wsUrl = 'ws://192.168.1.171:9080/v1/server/webgetapi'
const wsInstance = new WebSocketCli(wsUrl)

// 导出对象
export default wsInstance

vue使用的时候,需要注意:最好不要封装到自定义hooks里面,否则可能会出现注册后的消息为空的情况:然后就会导致消息监听失效

相关推荐
青瓦梦滋32 分钟前
WebSocket协议
linux·服务器·网络·c++·websocket·网络协议·http
变与不变8062 小时前
jQuery怎么使用
前端·javascript
神膘护体小月半3 小时前
flex 布局的 order 属性
前端·css
paopaokaka_luck3 小时前
流浪动物救助与收养系统(DeepSeek AI对话、 ECharts多维分析、救助流程衔接、领养与回访衔接、 捐赠确认与公示、志愿者协作)
java·前端·javascript·人工智能·mysql·echarts·推荐算法
仰望.3 小时前
vue 表格组件 vxe-table 树表格懒加载支持拖拽排序的详细用法
前端·javascript·vue.js·vxe-table
前端 贾公子3 小时前
vite-plugin-uni-manifest 升级指南
前端
小码哥_常3 小时前
iPhone 用户传了张 HEIC,我的前端崩了
前端
小码哥_常3 小时前
你发的原图可能暴露你家地址——聊聊图片 EXIF 隐私
前端
java1234_小锋3 小时前
【技术专题】CSS3 网页技术 - CSS3 优先级
前端·css·css3
IpdataCloud3 小时前
批量查IP的API接口怎么选?免费API配额瓶颈与离线库本地批量方案实测
网络·网络协议·tcp/ip