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

相关推荐
运筹vivo@1 天前
BUUCTF: [SUCTF 2019]EasySQL
前端·web安全·php
holeer1 天前
14步入门Vue|cn.vuejs.org教程学习笔记
前端·javascript·vue.js·笔记·前端框架·教程·入门
是席木木啊1 天前
RuoYi-Vue-Plus UI前端页面布局调整
前端·vue.js·ui
Web极客码1 天前
WordPress 6.8有哪些新特性
前端·javascript·html
UXbot1 天前
UI设计工具推荐合集
前端·人工智能·ui
码路星河1 天前
基于 Vue + VueUse 的 WebSocket 优雅封装:打造高可用的全局连接管理方案
javascript·vue.js·websocket
敲敲了个代码1 天前
如何优化批量图片上传?队列机制+分片处理+断点续传三连击!(附源码)
前端·javascript·学习·职场和发展·node.js
@AfeiyuO1 天前
Vue 引入全局样式scss
前端·vue·scss
光影少年1 天前
flex布局和grid布局区别,实现两边固定布局中间自适应
前端·css3·web·ai编程
全栈测试笔记1 天前
异步函数与异步生成器
linux·服务器·前端·数据库·python