| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- import useStore from '@/pages/store'
- import { injectable, Service } from './service'
- @injectable
- export default class SocketService extends Service {
- private _socket: WebSocket | null = null
- private _reconnectTimeout: string | number | NodeJS.Timeout | undefined = undefined
- private _ping = JSON.stringify({ event: 'heartbeat', content: 'ping' })
- private _reconnectTime = 3000
- private _heartInterval: string | number | NodeJS.Timeout | undefined = undefined
- private _messageTime = 0
- private _store = useStore()
- /**
- * 连接
- */
- private _connect() {
- const { token } = this._store
- if (!token) return null
- const url = `${import.meta.env.VITE_SOCKET_API}/${token}`
- const socket = new WebSocket(url)
- socket.onerror = this._onError.bind(this)
- socket.onopen = this._onOpen.bind(this)
- socket.onmessage = this._onMessage.bind(this)
- socket.onclose = this._onClose.bind(this)
- this._socket = socket
- return socket
- }
- /**
- * 重连
- */
- private _reConnect() {
- this._onClose()
- this._reconnectTimeout = setTimeout(() => {
- this._socket = this._connect()
- console.log('网络连接已断开,正在尝试重新连接...')
- }, this._reconnectTime)
- }
- /**
- * 连接错误,重连
- */
- private _onError() {
- this._reConnect()
- }
- /**
- * 连接打开,心跳检测
- */
- private _onOpen() {
- this._socket?.send(this._ping)
- }
- /**
- * 心跳检测
- */
- private _heartbeat(iTime: number, pTime: number) {
- const t = new Date().getTime()
- if (this._heartInterval) clearInterval(this._heartInterval)
- return setTimeout(() => {
- if ((t - this._messageTime) > pTime) {
- this._reConnect()
- }
- this._socket?.send(this._ping)
- }, iTime)
- }
- /**
- * 接收消息
- */
- private _onMessage(evt: Any) {
- this._messageTime = new Date().getTime()
- const data = JSON.parse(evt.data)
- if (data.event === 'connect') {
- const iTime = data.content.ping_interval * 1000
- const pTime = data.content.ping_timeout * 1000
- this._heartInterval = this._heartbeat(iTime, pTime)
- } else {
- this._store.setSocketData(data)
- }
- }
- /**
- * 关闭连接
- */
- private _onClose() {
- clearTimeout(this._reconnectTimeout)
- clearInterval(this._heartInterval)
- this._socket = null
- }
- /** 链接 */
- public connect() {
- return this._connect()
- }
- /** 关闭 */
- public close() {
- if (this._socket) this._socket.close()
- this._store.setSocketData(null)
- this._onClose()
- }
- /**
- * 推送消息
- *
- */
- public emit(event: string, data: object) {
- const content = JSON.stringify({ event, data })
- if (!this._socket && this._socket!.readyState !== 1) return
- this._socket?.send(content)
- }
- }
|