Pro/public/static/deal/js/webSocket.js
2026-02-25 01:50:31 +08:00

197 lines
6.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

class WebSocketClass {
constructor (wsUrl) {
this.successFn = {} // 成功的回掉函数
this.wsUrl = wsUrl // 请求的url
this.errorCallBackFunArr = [] // 当推送异常时执行的数组
this.isConnection = false // 判断是否支持weosocket
this.isErrorCallBack = false
this.lockReconnect = false // 避免重复连接
this.ping = null
this.sendObj = {}
this.heartCheck()
this.createWebSocket()
}
createWebSocket () {
try {
this.webSocket = new WebSocket(this.wsUrl)
this.initEventHandle()
} catch (e) {
this.errorCallBackData()
this.reconnect(this.wsUrl)
}
}
initEventHandle () {
this.webSocket.onclose = () => {
this.errorCallBackData()
this.reconnect(this.wsUrl)
}
this.webSocket.onerror = () => {
this.errorCallBackData()
this.reconnect(this.wsUrl)
}
this.webSocket.onopen = () => {
this.isConnection = true
this.isErrorCallBack = false
clearInterval(this.ping)
this.ping = setInterval(() => {
this.send('{"event": "ping"}')
}, 10000)
// 心跳检测重置
this.heartCheck.start()
}
this.webSocket.onmessage = data => {
// 如果获取到消息,心跳检测重置
// 拿到任何消息都说明当前连接是正常的
this.heartCheck.start()
this.decodeData(data)
}
}
send(cmd) {
// 只有当 webSocket.readyState 为 OPEN才发送订阅
// readyState属性返回实例对象的当前状态共有四种。
// CONNECTING值为0表示正在连接。
// OPEN值为1表示连接成功可以通信了。
// CLOSING值为2表示连接正在关闭。
// CLOSED值为3表示连接已经关闭或者打开连接失败。
if (!cmd) {
return
}
// this.sendObj[cmd] && (delete clearTimeout(this.sendObj[cmd]))
if (this.webSocket.readyState === 1) { // 只有当链接打开时才进行订阅
this.webSocket.send(cmd)
}
// else if (this.webSocket.readyState === 0) { // 如果链接处于正在链接中,则进行延时订阅
// this.sendObj[cmd] = setTimeout(() => {
// this.send(cmd)
// }, 50)
// }
}
reconnect (url) {
if (this.lockReconnect) {
return
}
this.lockReconnect = true
// 没连接上会一直重连,设置延迟避免请求过多
setTimeout(() => {
this.createWebSocket(url)
this.lockReconnect = false
}, 2000)
}
errorCallBackData () {
this.isConnection = false
if (!this.isErrorCallBack && this.errorCallBackFunArr.length) {
this.isErrorCallBack = true
for (let i = 0, len = this.errorCallBackFunArr.length; i < len; i++) {
if ((typeof this.errorCallBackFunArr[i]) === 'function') {
this.errorCallBackFunArr[i]()
}
}
}
}
decodeData (data) {
if (data.data instanceof Blob) {
let blob = data.data
// js中的blob没有没有直接读出其数据的方法通过FileReader来读取相关数据
let reader = new FileReader()
reader.readAsArrayBuffer(blob)
// 当读取操作成功完成时调用.
reader.onload = (evt) => {
if (evt.target.readyState === FileReader.DONE) {
let result = new Uint8Array(evt.target.result)
// 如果后端进行压缩数据处理zlib那么要引入解析zlib的js
result = (new window.Zlib.RawInflate(result)).decompress()
let strResult = ''
let length = result.length
for (let i = 0; i < length; i++) {
strResult += String.fromCharCode(result[i])
}
this.callBackData(JSON.parse(strResult))
}
}
return
}
let d = JSON.parse(data.data)
// 如果后端需要等待则返回code10010过一段时间后重新订阅
if (d.code === '10010') {
let dt = {}
Object.assign(dt, d)
delete dt.code
delete dt.msg
setTimeout(() => {
this.send(JSON.stringify(dt))
}, 2000)
return
}
this.callBackData(JSON.parse(data.data))
}
callBackData (data) {
if (data instanceof Array) {
for (let i = 0; i < data.length; i++) {
this.doCallback(data[i])
}
} else if (data instanceof Object) {
if (data.hasOwnProperty('event') && data.event === 'pong') {
return
}
data.payload && (data.payload = JSON.parse(data.payload))
this.doCallback(data)
}
}
doCallback (data) {
if (data.event) {
let fn = this.successFn[data.event]
if (typeof fn === 'function') {
fn(data)
}
}
}
// 心跳检测
heartCheck () {
let that = this
this.heartCheck = {
timeout: 10000, // 10秒
timeoutObj: null,
serverTimeoutObj: null,
reset: function () {
clearTimeout(this.timeoutObj)
clearTimeout(this.serverTimeoutObj)
},
start: function () {
this.reset()
let self = this
this.timeoutObj = setTimeout(function () {
// 这里发送一个心跳,后端收到后,返回一个心跳消息
// onmessage拿到返回的心跳就说明连接正常
that.send('{"event": "ping"}')
self.serverTimeoutObj = setTimeout(function () { // 如果超过一定时间还没重置,说明后端主动断开了
// 如果onclose会执行reconnect我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
that.webSocket.close()
}, self.timeout)
}, this.timeout)
}
}
}
}
function webSocketFn (url) {
let wb = new WebSocketClass(url)
return {
webSocketSend: wb.send.bind(wb),
errorCallBackFunArr: wb.errorCallBackFunArr,
successFn: wb.successFn,
isConnection: function () {
return wb.isConnection
},
getSocketFile (webSocketData, ajaxData) {
let socketFail = (isFirst) => {
if (this.isConnection()) {
webSocketData()
} else {
ajaxData()
setTimeout(socketFail, 2000)
}
}
return socketFail
}
}
}