-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
75 lines (67 loc) · 2.12 KB
/
index.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
import { IntervalController, prcIntervalWithDelta } from "precision-timeout-interval";
type DeltaReceivingCallback = (delta: number) => any;
type CallbackInfo = {
fn: DeltaReceivingCallback,
timeout: number,
interval: number,
startTime: number,
repeats: boolean
}
export class VirtualTimer {
private callbacks: CallbackInfo[] = [];
private precision = 20;
private controller: IntervalController;
private time = 0;
constructor(precision?: number) {
this.precision = precision ?? 20;
this.controller = prcIntervalWithDelta(this.precision, this.#mainLoop.bind(this));
}
timeout(callback: DeltaReceivingCallback, milliseconds: number) {
const cbInfo = {
fn: callback,
repeats: false,
startTime: this.time,
interval: milliseconds,
timeout: this.time + milliseconds
};
this.callbacks.push(cbInfo);
return {
cancel: () => this.#remove(cbInfo)
}
}
interval(callback: DeltaReceivingCallback, milliseconds: number) {
const cbInfo = {
fn: callback,
repeats: true,
startTime: this.time,
interval: milliseconds,
timeout: this.time + milliseconds
};
this.callbacks.push(cbInfo);
return {
cancel: () => this.#remove(cbInfo)
}
}
#remove(c: CallbackInfo) {
this.callbacks = this.callbacks.filter((cb) => cb !== c);
}
#mainLoop(delta: number) {
this.time += delta;
for (let i = 0; i < this.callbacks.length; i++) {
const callback = this.callbacks[i];
if (callback.timeout <= this.time) {
callback.fn(this.time - callback.startTime);
if (callback.repeats) {
callback.startTime = this.time;
callback.timeout = callback.startTime + callback.interval;
} else {
this.callbacks.splice(i, 1);
}
}
}
}
end() {
this.callbacks = [];
this.controller.cancel();
}
}