-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathping.ts
84 lines (61 loc) · 1.51 KB
/
ping.ts
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
import { ClientSocket } from './socket'
const initialDelay = 1000
const delayBetweenPings = 10000
const keepRecentPingCount = 10
const avg = (values: number[]) => values.reduce((a, b) => a + b) / values.length
export default class Ping {
#socket: ClientSocket
#timeout: NodeJS.Timeout | undefined
readonly #pings: number[]
#average: number
#delta: number
#isDirty: boolean
constructor(socket: ClientSocket) {
this.#socket = socket
this.#pings = []
this.#average = NaN
this.#delta = NaN
this.#isDirty = false
}
#update() {
const start = Date.now()
this.#socket.emit('ping', () => {
this.#pings.push(Date.now() - start)
while (this.#pings.length > keepRecentPingCount) {
this.#pings.shift()
}
this.#isDirty = true
})
this.#timeout = setTimeout(this.#update.bind(this), delayBetweenPings)
}
#updateCache() {
this.#average = Math.round(avg(this.#pings))
this.#delta = Math.round(
avg(this.#pings.map((d) => Math.abs(d - this.#average))),
)
this.#isDirty = false
}
get average(): number {
if (this.#isDirty) {
this.#updateCache()
}
return this.#average
}
get delta(): number {
if (this.#isDirty) {
this.#updateCache()
}
return this.#delta
}
start() {
this.stop()
this.#timeout = setTimeout(this.#update.bind(this), initialDelay)
}
stop() {
if (!this.#timeout) {
return
}
clearTimeout(this.#timeout)
this.#timeout = undefined
}
}