WebSocket 的简单用法
// 与服务器定义的返回字段信息
enum SocketEvents {
taken_offline = "taken_offline"
}
export { SocketEvents }
interface SocketEvent {
event: SocketEvents,
message: string,
data: any
}
type SocketEventListener = (event: SocketEvent) => void
type removeEventListen = () => void
/**
* 创建一个websocket的构造函数! 结合发布订阅模式
*/
class SocketManager {
private socket!: WebSocket
private socketListeners = new Set<SocketEventListener>()
private isConnect = false
private isTimeout = false
private keepAliveTimeInterval!: NodeJS.Timeout
private checkTimeoutTimer!: NodeJS.Timeout
private reTryTimes = 0 // 重连次数
public async start() {
// 设置需要建立联系的地址
let cashierWssAddress = ""
if (process.env.NODE_ENV === "development") {
cashierWssAddress = "https://xxxx.xxxx.xx".replace('https', "wss")
} else {
cashierWssAddress = '生成环境地址'.replace('https', "wss")
}
this.socket = new WebSocket(cashierWssAddress)
this.socket.onopen = this.onOpen.bind(this)
this.socket.onmessage = this.onMessage.bind(this)
this.socket.onerror = this.onError.bind(this)
this.socket.onclose = this.onClose.bind(this)
}
public stop() {
if (this.socket) {
this.socket.close()
}
clearInterval(this.checkTimeoutTimer)
clearInterval(this.keepAliveTimeInterval)
}
public addEventListener(fn: SocketEventListener): removeEventListen {
this.socketListeners.add(fn)
return () => {
this.socketListeners.delete(fn)
}
}
public removeEventListener(fn: SocketEventListener) {
this.socketListeners.delete(fn)
}
private onOpen(event: Event) {
console.log('socket 建立连接')
this.isConnect = true
this.reTryTimes = 0
this.keepAlive()
}
private onMessage(event: MessageEvent) {
const data = JSON.parse(event.data)
console.log('socket 收到消息', data)
this.dispathEvent(data)
if (this.checkTimeoutTimer) {
clearTimeout(this.checkTimeoutTimer)
}
this.isTimeout = false
this.checkTimeoutTimer = setTimeout(() => {
if (this.isConnect) {
this.isTimeout = true
console.log('socket 连接超时')
}
}, 40 * 1000)
}
private onError(event: Event) {
if (this.reTryTimes < 5) {
console.log("连接失败")
} else {
console.log('socket 通信错误', event)
this.isConnect = false
// openMessage(MessageType.error, "socket连接失败,将无法使用系统")
setTimeout(() => {
// System.logout().then(() => {
// window.location.href = PASSPORT_DOMAIN + '/#/login?oa=new_ls'
// })
}, 3 * 1000)
}
}
private onClose(ev: CloseEvent) {
console.log('socket 连接关闭')
this.isConnect = false
if (this.reTryTimes < 5) {
this.reTryTimes++
// openMessage(MessageType.info, "socket 断开连接,尝试第" + this.reTryTimes + "次重连")
setTimeout(() => {
this.start()
}, 3 * 1000)
}
}
private keepAlive() {
clearInterval(this.keepAliveTimeInterval) // 防止重复调用
this.keepAliveTimeInterval = setInterval(() => {
if (!this.isConnect) {
return clearInterval(this.keepAliveTimeInterval)
}
if (this.isTimeout) {
return this.start()
}
if (this.socket) {
this.socket.send('❤️')
} else {
clearInterval(this.keepAliveTimeInterval)
}
}, 10 * 1000)
}
private dispathEvent(event: SocketEvent) {
this.socketListeners.forEach(fn => fn(event))
}
}
const socketManager = new SocketManager()
socketManager.addEventListener((socketEvent) => {
switch (socketEvent.event) {
case SocketEvents.taken_offline:
// reactHistory.push("/noSeat")
break
}
})
export {
socketManager
}
一份帮助文档,无论多么仔细,都不会帮助主人多敲一行代码!