index.ts
2.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import type { UseWebSocketReturn } from '@vueuse/core'
import { useWebSocket } from '@vueuse/core'
import { WebsocketCmd } from './type/service'
import type { WsService, WsSubscriber } from './type/service'
import { useGlobSetting } from '@/hooks/setting'
import { getJwtToken, getShareJwtToken } from '@/utils/auth'
import { isShareMode } from '@/utils/env'
const RECONNECT_INTERVAL = 3000
const MAX_RECONNECT_COUNT = 20
// const WS_IDLE_TIMEOUT = 90000
const MAX_PUBLISH_COMMANDS = 10
export abstract class CmdWrapper {
abstract hasCommands(): boolean
abstract clear(): void
abstract preparePublishCommands(maxCommands: number): CmdWrapper;
[key: string]: WebsocketCmd | any;
}
export abstract class WebsocketService<T extends WsSubscriber, D = any> implements WsService<T> {
lastCmdId = 0
subscribersCount = 0
subscribersMap = new Map<number, T>()
socketUrl: string
data: UseWebSocketReturn<D>['data']
status: UseWebSocketReturn<D>['status']
ws: UseWebSocketReturn<D>['ws']
close: UseWebSocketReturn<D>['close']
open: UseWebSocketReturn<D>['open']
send: UseWebSocketReturn<D>['send']
protected constructor(public cmdWrapper: CmdWrapper) {
const { socketUrl } = useGlobSetting()
const { protocol, hostname } = window.location
let socketProtocol
let prot
if (protocol === 'https') {
socketProtocol = 'wss:'
prot = 443
}
else {
socketProtocol = 'ws:'
prot = 80
}
this.socketUrl = socketUrl ? `${socketUrl}${isShareMode() ? getShareJwtToken() : getJwtToken()}` : `${socketProtocol}//${hostname}:${prot}`
const { data, status, ws, close, open, send } = useWebSocket<D>(this.socketUrl, {
autoReconnect: {
delay: RECONNECT_INTERVAL,
retries: MAX_RECONNECT_COUNT,
},
immediate: false,
onMessage: (_ws, event) => {
if (event.data) {
const message = JSON.parse(event.data)
if (message.errorCode) {
// handle error
}
else {
this.processOnMessage(message)
}
}
},
})
this.data = data
this.status = status
this.ws = ws
this.close = close
this.open = open
this.send = send
}
abstract update(subscriber: T): void
abstract unsubscribe(subscriber: T): void
abstract subscribe(subscriber: T): void
abstract processOnMessage(message: any): void
protected nextCmdId() {
this.lastCmdId++
return this.lastCmdId
}
protected publishCommands() {
const command = this.cmdWrapper.preparePublishCommands(MAX_PUBLISH_COMMANDS)
this.send(JSON.stringify(command))
}
openSocket() {
this.open()
}
}