WebSocket包装类

WebSocket 包装器

  • 支持心跳
  • 支持自动重连

使用

    import webSocketWrapper from "@/utils/WebSocketWrapper";
    //连接
    webSocketWrapper.connect(`ws://172.16.0.148:8887/printer`)
    //日志
    webSocketWrapper.logFactory( (message)=>{
    console.log(message)
    })
    //接受数据
    webSocketWrapper.onDataReceive( (data)=>{
    console.log(data)
    })
    //发送信息
    webSocketWrapper.send(message)
    //关闭
    webSocketWrapper.close()

包装器源码

/*************************
 * WebSocket Client 包装器
 * 2023年3月6日09:47:10
 *************************/
//重连前关闭已有链接的代码,这个目前来说获取不到
const CLOSE_CODE_RECONNECT = 3000

//心跳间隔时间,5秒发送一次ping 毫秒
const PING_TIME = 5000
/**
 * 重连倒计时 毫秒
 * @type {number}
 */
const RECONNECT_DOWN_TIME = 5000
/**
 * 默认IP
 * @type {string}
 */
const DEFAULT_IP = '127.0.0.1'
/**
 * 默认端口
 * @type {string}
 */
const DEFAULT_PORT = '8887'

/**
 * 默认路径
 * eg. ws://192.168.1.100/8887/test
 * 其中DEFAULT_PATH的值为 /test
 */
const DEFAULT_PATH = ''
/**
 * webSocket实例
 * @type WebSocket
 */
let webSocket = null
/**
 * ping 定时方法返回的id
 * @type {number}
 */
let pingIntervalId = -1
/**
 * 重新连接 定时方法返回的id
 */
let reconnectIntervalId = -1
/**
 * 剩余的重连时间 毫秒
 * 初始值为RECONNECT_DOWN_TIME的值,减到0后进行重连
 */
let reconnectDownTime
/**
 * 缓存websocket服务器地址,用于重连
 */
let serverUrl = ''
/**
 * 日志回调函数
 * @type {Function}
 */
let logCallback = null
/**
 * 数据回调函数
 * @type {Function}
 */
let dataCallback = null
/**
 * 自动连接标识
 * @type {boolean} true 自动连接
 */
let autoReconnectFlag = true
/**
 * 心跳包标识
 * @type {boolean} true 发送心跳包
 */
let heartFlag = true
/**
 * 日志输出
 * @param message
 * @constructor
 */
const Log = (message) => {
    if (!!logCallback && (logCallback instanceof Function)) {
        logCallback(message)
    }
}

/**
 * 开启ping服务器
 * 1.关闭已开启的ping定时方法。
 * 2.如果开启心跳包,则重新调用定时函数,每隔PING_TIME发送一次ping字符串
 */
const startPingServer = () => {
    endPingServer()
    if (!heartFlag) {
        return
    }
    pingIntervalId = setInterval(() => {
        if (!webSocket || webSocket.readyState !== WebSocket.OPEN) {
            return
        }
        webSocket.send('ping')
    }, PING_TIME)
}
/**
 * 结束ping服务器
 */
const endPingServer = () => {
    if (pingIntervalId !== -1) {
        clearInterval(pingIntervalId)
        pingIntervalId = -1
    }
}

/**
 * 发生错误时自动重连 5秒钟后自动重连
 * 1.关闭ping定时方法
 * 2.判断自动重连标识,false不自动重连
 * 3.关闭自动重连定时方法
 * 4.设置重连定时方法。这里使用定时方法主要是为了给用户提示:.xx后重新连接...
 */
const reconnect = () => {
    endPingServer()
    endReconnect()
    //不进行自动连接
    if (!autoReconnectFlag) {
        return
    }
    reconnectIntervalId = setInterval(() => {
        Log(`${reconnectDownTime / 1000}后重新连接...`)
        reconnectDownTime -= 1000
        if (reconnectDownTime <= 0) {
            reconnectDownTime = RECONNECT_DOWN_TIME
            Log('正在重新连接...')
            if (serverUrl === '') {
                console.error(`WebSocket服务端地址错误:${serverUrl}`)
                return
            }
            connect(serverUrl, autoReconnectFlag, heartFlag)
        }
    }, 1000)
}
/**
 * 结束重连
 */
const endReconnect = () => {
    if (reconnectIntervalId !== -1) {
        Log('结束重新连接倒计时...')
        clearInterval(reconnectIntervalId)
        reconnectIntervalId = -1
    }
}
/**
 * webSocket连接
 * @param url websocket服务端地址
 * @param autoReconnect 异常关闭后是否自动连接 true 自动连接 false 不自动连接
 */
const connect = (url = `ws://${DEFAULT_IP}:${DEFAULT_PORT}${DEFAULT_PATH}`, autoReconnect = true, heart = true) => {
    if (!url) {
        console.error(`WebSocket服务端地址错误:${url}`)
        return
    }
    //1.初始化url、重连标识
    autoReconnectFlag = autoReconnect
    heartFlag = heart
    serverUrl = url
    //2.关闭已经连接客户端
    close()
    //3.设置重连倒计时
    reconnectDownTime = RECONNECT_DOWN_TIME
    Log(`正在连接服务器[${serverUrl}]...`)
    //4.实例化websocket
    webSocket = new WebSocket(url)
    /**
     * 当readyState变为OPEN时被调用 开启事件监听器,意味着当前连接已经准备好发送和接受数据了
     * @param event
     */
    webSocket.onopen = (event) => {
        Log('webSocket连接已打开')
        // Log(event)
        startPingServer()
    }
    /**
     * 在webSocket 的readyState变为ClOSED是被调用  关闭事件监听器
     * @param closeEvent 名为close的事件
     */
    webSocket.onclose = (closeEvent) => {
        Log('已与服务器断开连接')
        // Log(closeEvent)
        reconnect()
    }
    /**
     * 当webSocket的连接由于一些错误事件的发生而被关闭时将会触发此监听器
     * @param event
     */
    webSocket.onerror = (event) => {
        // Log(event)
    }
    /**
     * 在websocket 接受到服务端的消息时触发此事件
     * @param event
     */
    webSocket.onmessage = (event) => {
        // Log(event)
        if (!!dataCallback && (dataCallback instanceof Function)) {
            dataCallback(event.data)
        }
    }
}

/**
 * 关闭连接
 */
const close = () => {
    endPingServer()
    endReconnect()
    if (!!webSocket) {
        //重新设置事件监听器
        webSocket.onclose = (closeEvent) => {
            Log('关闭服务')
        }
        //code 只能是1000 或者 3000到4999 否则会报错  INVALID_ACCESS_ERR
        //reason 不能超过123个字节   SYNTAX_ERR
        //目前来说这个码是不好使的在onclose中获取不到
        webSocket.close(CLOSE_CODE_RECONNECT, 'WebSocket连接前关闭已有链接')
    }
}
/**
 * 日志工厂
 * @param callback 工厂回调
 */
const logFactory = (callback) => {
    logCallback = callback
}
/**
 * 接受数据
 * @param callback 数据u回调
 */
const onDataReceive = (callback) => {
    dataCallback = callback
}
/**
 * 发送消息
 * @param message 消息内容
 */
const send = (message) => {
    if (!!webSocket) {
        webSocket.send(message)
    }
}
/**
 * websocket信息
 */
const info = () => {
    if (!!webSocket) {
        return {
            binaryType: webSocket.binaryType,//使用的二进制数据类型
            bufferedAmount: webSocket.bufferedAmount,//未发送值服务器的字节数
            extensions: webSocket.extensions,//服务器选择的扩展 没啥用
            protocol: webSocket.protocol,//服务器选择的下属协议
            url: webSocket.url,//绝对路径
            readyState: webSocket.readyState//当前连接状态
        }
    }
    return {}
}
/*
 * 包装器
 */
const Wrapper = () => {
    return {
        connect,
        logFactory,
        send,
        close,
        info,
        onDataReceive
    }
}

export default Wrapper()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

英杰丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值