websocket 重连封装


/**  * websocket 类  *  * 回调方法和原生websocket保持一致  * @param {String} url 连接地址  * @param {Boolean} isReconnect 是否包含重连机制  *    定时向后端发送 'ping' 后端收到后返回对应值,以此检测连接是否在线  *    如不在线则定时发起重连  * @param {Object} options 配置参数  * **/ class Ws {   constructor(url, isReconnect = true, options = {}) {     if (url) {       if (typeof options === 'object') {         this.opt = {           url: url, // 连接地址           // 心跳检测           isReconnect: isReconnect, // 是否开启重连           timeout: 4000, // 超时时间,超过后则发起重连           pingString: 'ping', // 检测标识           intervalStep: 3000, // 定时ping服务时间           reconnectStep: 3000 // 设置重连间隔,防止重复连接         }         this.opt = {           ...this.opt,           ...options         }         this.lockReconnect = false // 重连锁,避免频繁重连         this.isClose = false         this.onopen = () => {} // 创建打开连接回调         this.onmessage = () => {} // 收到消息通知的回调         this.onclose = () => {} // 关闭连接的回调         this.onerror = () => {} // 连接错误回调         this.timeoutObj = null // 心跳检测计时器         this.intervalObj = null // 定时发送计时器         this.reconnectTimer = null // 避免重连锁         this.createWs()       } else {         console.error('options need object')       }     } else {       console.error('ur is required')     }   }   // 创建ws   createWs() {     if (this.ws) {       this.close()     }     this.ws = new WebSocket(this.opt.url)     this.isClose = false     this.setWsData()     this.ws.onopen = () => {       if (this.opt.isReconnect) {         this.ping()         this.reset().start()       }       this.onopen()     }     this.ws.onmessage = (data) => {       if (this.opt.isReconnect && data.data === this.opt.pingString) {         this.reset().start()       } else {         this.onmessage(data)       }     }     this.ws.onclose = () => {       if (this.opt.isReconnect) this.reconnect()       this.onclose()     }     this.ws.onerror = () => {       if (this.opt.isReconnect) this.reconnect()       this.onerror()     }   }   // 设置ws参数   setWsData() {     if (this.ws) {       this.binaryType = this.ws.binaryType       this.bufferedAmount = this.ws.bufferedAmount       this.protocol = this.ws.protocol       this.readyState = this.ws.protocol     } else {       this.binaryType = ''       this.bufferedAmount = null       this.protocol = ''       this.readyState = null     }   }   // 发送消息   send(data) {     this.ws.send(data)     return this   }   // 关闭连接   close() {     this.isClose = true     this.ws.close()     return this   }   // 清除定时器   clearTimer() {     if (this.reconnectTimer) {       clearTimeout(this.reconnectTimer)     }     if (this.timeoutObj) {       clearTimeout(this.timeoutObj)     }     if (this.intervalObj) {       clearTimeout(this.intervalObj)     }   }   // 开启心跳   start() {     this.timeoutObj = setTimeout(() => {       this.reconnect()     }, this.opt.timeout)     return this   }   // 重置心跳   reset() {     clearTimeout(this.timeoutObj)     return this   }   // 重连   reconnect() {     if (this.isClose) {       this.clearTimer()       return     }     if (this.lockReconnect) return     this.lockReconnect = true     if (this.reconnectTimer) clearTimeout(this.reconnectTimer)     this.reconnectTimer = setTimeout(() => {       this.createWs()       this.lockReconnect = false     }, this.opt.reconnectStep)     return this   }   // ping   ping() {     if (this.opt.isReconnect) {       if (this.intervalObj) clearTimeout(this.intervalObj)       this.intervalObj = setTimeout(() => {         if (this.isClose) {           this.clearTimer()         } else {           try {             if (this.ws) {               this.ws.send(this.opt.pingString)               this.ping()             }           } catch (e) {             console.info('ws ping error:', e)           }         }       }, this.opt.intervalStep)     }   } }