前端封装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里面,否则可能会出现注册后的消息为空的情况:然后就会导致消息监听失效

相关推荐
DP DPharness5 分钟前
StudyMate 从安装到第一节课的完整操作路径
人工智能·websocket·网络协议·智能手机·dpharness
库拉镜像AI牛牛31 分钟前
短剧内容自动化生产:知漫剧工作室落地教程
大数据·服务器·前端·人工智能·语音识别
律宏阔33 分钟前
Flutter 列表图片内存优化:CachedNetworkImage 与 ClipRRect 的取舍
前端·flutter
行者全栈架构师33 分钟前
【鸿蒙心迹】相册文搜图工程化落地:HarmonyOS 7.0 端侧 AI 检索全链路实战与 5 个踩坑解法
前端
律宏阔43 分钟前
Dart 3 Record:解决 Future.wait 异构返回值的类型问题
前端·flutter
Seraphina361 小时前
DVWA(XSS Reflected/Stored High,CSRF Low)
前端·xss·csrf
默_笙2 小时前
🍔 中间件不只是打日志:四个钩子、一次短路,和自带的工具
前端·javascript
程序员老赵2 小时前
Docker 部署 Dolibarr:轻松搭建开源 ERP/CRM 平台
运维·前端·后端
星禾元亨3 小时前
同一件事有三份资料,AI 该信哪一份?冲突判定、优先级链与处置流程
前端·人工智能
Dovis(誓平步青云)3 小时前
家里设备越来越多,如何用一张空间地图控制灯光和温度![
android·java·前端·javascript·人工智能·电脑