export default class WebSocketClass {
/**
* @description: 初始化实例属性,保存参数
* @param {String} url ws的接口
* @param {Function} msgCallback 服务器信息的回调传数据给函数
* @param {String} name 可选值 用于区分ws,用于debugger
*/
constructor(url, msgCallback, name = 'websocket') {
this.url = url
this.msgCallback = msgCallback
this.name = name
this.ws = null // websocket对象
this.status = null // websocket是否关闭
this.lockReconnect = false //是否真正建立连接
this.reconnectTimer = null //断开 重连倒计时
}
/**
* @description: 初始化 连接websocket或重连webSocket时调用
* @param {*} 可选值 要传的数据
*/
connect(data) {
// 新建 WebSocket 实例
this.ws = new WebSocket(this.url)
this.ws.onopen = (e) => {
// 连接ws成功回调
this.status = 'open'
console.log(`${this.name}连接成功`, e)
// this.heartCheck();
if (data !== undefined) {
// 有要传的数据,就发给后端
return this.ws.send(data)
}
}
// 监听服务器端返回的信息
this.ws.onmessage = (e) => {
// 把数据传给回调函数,并执行回调
// if (e.data === 'pong') {
// this.pingPong = 'pong'; // 服务器端返回pong,修改pingPong的状态
// }
return this.msgCallback(e.data)
}
// ws关闭回调
this.ws.onclose = (e) => {
this.closeHandle(e) // 判断是否关闭
}
// ws出错回调
this.onerror = (e) => {
this.closeHandle(e) // 判断是否关闭
}
}
heartCheck() {
// 心跳机制的时间可以自己与后端约定
this.pingPong = 'ping' // ws的心跳机制状态值
this.pingInterval = setInterval(() => {
if (this.ws.readyState === 1) {
// 检查ws为链接状态 才可发送
this.ws.send('ping') // 客户端发送ping
}
}, 10000)
this.pongInterval = setInterval(() => {
if (this.pingPong === 'ping') {
this.closeHandle('pingPong没有改变为pong') // 没有返回pong 重启webSocket
}
// 重置为ping 若下一次 ping 发送失败 或者pong返回失败(pingPong不会改成pong),将重启
console.log('返回pong')
this.pingPong = 'ping'
}, 20000)
}
// 发送信息给服务器
sendHandle(data) {
console.log(`${this.name}发送消息给服务器:`, data)
return this.ws.send(data)
}
closeHandle(e = 'err') {
// 因为webSocket并不稳定,规定只能手动关闭(调closeMyself方法),否则就重连
if (this.status !== 'close') {
console.log(`${this.name}断开,重连websocket`, e)
this.reconnect() // 重连
} else {
console.log(`${this.name}websocket手动关闭`)
}
}
// 手动关闭WebSocket
closeMyself() {
console.log(`关闭${this.name}`)
this.status = 'close'
return this.ws.close()
}
//重新连接 1s,设置延迟避免请求过多
reconnect() {
//设置lockReconnect变量避免重复连接
if (this.lockReconnect) return
this.lockReconnect = true
this.reconnectTimer && clearTimeout(this.reconnectTimer)
this.reconnectTimer = setTimeout(() => {
this.connect()
this.lockReconnect = false
}, 1000)
}
}