代码(可直接使用)
import path from '_api/axios/addressConfig'
import { getStore } from '@/tools/session'
interface OnMessageIter {
(event: MessageEvent):any
}
interface HeartbeatKey {
[key:string]:any
}
interface HeartbeatIter extends HeartbeatKey {
detectionTimer:number
timeoutTimer:number
reconnectTimer:number
sendTimer:number
isConnected:boolean
stopReconnect:boolean
clearTimer: (key:string) => void
start: (instance:any) => void
reconnect: (instance:any) => void
resetHeart: (instance:any) => void
sendMsg: (instance:any) => void
}
interface WebSocketIter {
instance:WebSocket | null
open:(this:WebSocket, event: Event) => any
close:(this: WebSocket, event: CloseEvent) => any
error:(this: WebSocket, event: Event) => any
init:(message:OnMessageIter, url?:string) => void
sendToken:() => boolean
closeConnection: () => void
heartbeat:HeartbeatIter
}
let durableMessageFn:OnMessageIter | null = null
const middlewareSocket:WebSocketIter = {
instance: null,
open: function (this:WebSocket, event: Event) {
console.log('webSocket连接成功 ...')
middlewareSocket.sendToken()
middlewareSocket.heartbeat.start(middlewareSocket)
middlewareSocket.heartbeat.sendMsg(middlewareSocket)
},
close: function (this: WebSocket, event: CloseEvent) {
console.log('webSocket 断开: ' + event.code + ' ' + event.reason + ' ' + event.wasClean)
middlewareSocket.heartbeat.reconnect(middlewareSocket)
},
error: function (this: WebSocket, event: Event) {
console.log('连接错误', event)
middlewareSocket.heartbeat.reconnect(middlewareSocket)
},
init: function (message, url = `ws://${path.wsUrl}/ws`) {
if (this.instance?.readyState === 1) {
console.warn('已存在连接')
return
}
durableMessageFn = message
this.instance = new WebSocket(url)
this.instance.onmessage = function (this:WebSocket, event:MessageEvent) {
console.log(event, '数据')
middlewareSocket.heartbeat.resetHeart(middlewareSocket)
message(event)
}
this.instance.onopen = this.open
this.instance.onclose = this.close
this.instance.onerror = this.error
},
sendToken: function ():boolean {
const token:string | null = getStore('token')
if (this.instance?.readyState === 1 && token) {
this.instance?.send(`token:"${token}`)
return true
}
return false
},
closeConnection: function () {
this.instance?.close()
},
heartbeat: {
detectionTimer: 0,
timeoutTimer: 0,
reconnectTimer: 0,
sendTimer: 0,
isConnected: false,
stopReconnect: false,
clearTimer: function (key:string) {
if (this[key] !== 0) {
clearTimeout(this[key])
this[key] = 0
}
},
start: function (instance:WebSocketIter) {
this.clearTimer('detectionTimer')
this.clearTimer('timeoutTimer')
this.detectionTimer = setTimeout(() => {
this.isConnected = instance.sendToken()
if (!this.isConnected) {
this.reconnect(instance)
this.timeoutTimer = setTimeout(() => {
console.warn('websocket重连超时')
instance.closeConnection()
}, 30 * 1000)
}
}, 5 * 1000)
},
reconnect: function (instance:WebSocketIter) {
if (this.stopReconnect) {
return
}
this.stopReconnect = true
instance.closeConnection()
console.warn('尝试重新连接websocket')
this.clearTimer('reconnectTimer')
this.reconnectTimer = setTimeout(() => {
instance.init(durableMessageFn as OnMessageIter)
this.stopReconnect = false
}, 20 * 1000)
},
resetHeart: function (instance:WebSocketIter) {
this.clearTimer('detectionTimer')
this.clearTimer('timeoutTimer')
this.start(instance)
},
sendMsg: function (instance:WebSocketIter) {
clearInterval(this.sendTimer)
this.sendTimer = setInterval(() => {
if (!(instance.sendToken())) {
this.reconnect(instance)
clearInterval(this.sendTimer)
}
}, 10 * 1000)
}
}
}
export default middlewareSocket
use
middlewareSocket.init(function (event:MessageEvent) {
console.log(event)
console.log('收到服务器数据: ' + event.data)
})
|