webSocket TS 類封裝,包含心跳機制,以及斷線重連
/**
* @author yang
* @description socket封裝
* @time 2021/11/1
* */
interface Ioptions {
// token
token?: string;
// 發送心跳間隔時間
heart_time?: number;
//檢查鏈接狀態時間
check_time?: number;
//斷線后重連間隔時間
lock_time?: number;
}
let createSocket = (url: string, callback: (e: any) => void) => {
class Ws {
private url: string = url //socket 地址
private callback: (e: any) => void = callback
private heart_time: number = 3000 //心跳時間
private check_time: number = 3000 //檢查鏈接狀態時間
private lock_time: number = 4000 //重連時間
public ws: WebSocket | undefined //socket實例
private h_timer: NodeJS.Timeout | undefined //心跳定時器
private c_timer: NodeJS.Timeout | undefined //檢查鏈接定時器
private l_timer: NodeJS.Timeout | undefined //重連定時器
private isLock: boolean = false //重連鎖
private token: string | undefined //token
public init(options: Ioptions = {}): void {
let { token, heart_time, check_time, lock_time } = options
if (token) {
this.token = token
}
if (heart_time) {
this.heart_time = heart_time
}
if (check_time) {
this.check_time = check_time
}
if (lock_time) {
this.lock_time = lock_time
}
if (this.url == '') {
throw new Error('socket鏈接地址不能為空')
}
this.wsInit()
}
// 處理有token時的socket鏈接地址
private getUrl(): string {
if (this.token !== undefined) {
return `${this.url}?token=${this.token}`
} else {
return `${this.url}`
}
}
// 初始化socket
public wsInit(): void {
let ws = new WebSocket(this.getUrl())
ws.onopen = () => {
this.heartCheck()
}
ws.onclose = () => {
this.reconnect()
}
ws.onerror = () => {
this.reconnect()
}
ws.onmessage = (e) => {
this.heartCheck()
this.callback(e)
}
this.ws = ws
}
// 心跳
private heartCheck(): void {
this.h_timer && clearTimeout(this.h_timer)
this.c_timer && clearTimeout(this.c_timer)
this.h_timer = setTimeout(() => {
(this.ws as WebSocket).send('type:ping')
this.c_timer = setTimeout(() => {
if ((this.ws as WebSocket).readyState !== 1) {
(this.ws as WebSocket).close()
}
}, this.check_time)
}, this.heart_time)
}
// 重連
private reconnect(): void {
if (this.isLock) {
return
}
this.isLock = true
this.l_timer && clearTimeout(this.l_timer)
this.l_timer = setTimeout(() => {
this.wsInit()
this.isLock = false
}, this.lock_time)
}
}
return new Ws
}
export {
createSocket
}
未測試
