forked from burnedikt/diasend-nightscout-bridge
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLooper.ts
57 lines (51 loc) · 1.67 KB
/
Looper.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
import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";
dayjs.extend(relativeTime);
export class Looper<TLoopArgs = void> {
intervalMs: number;
loopingFun: (args?: TLoopArgs) => Promise<TLoopArgs>;
timeoutHandle: NodeJS.Timeout | undefined | number;
name: string;
constructor(
intervalMs: number,
loopingFun: (args?: TLoopArgs) => Promise<TLoopArgs>,
name: string
) {
this.intervalMs = intervalMs;
this.loopingFun = loopingFun;
this.name = name;
}
loop(args?: TLoopArgs) {
let nextArgs: TLoopArgs | undefined;
// run the looping function, then schedule the next run (unless it should be stopped)
void this.loopingFun(args)
.then((argsCalculatedByLoop) => {
// schedule next run with the new args calcualted by this run
nextArgs = argsCalculatedByLoop;
})
.catch((error) => {
console.error(error);
// retry with the current set of args
nextArgs = args;
})
.finally(() => {
// if this.timeoutHandle is set to 0 when we get here, don't schedule a re-run. This is the exit condition
// and prevents the synchronization loop from continuing if the timeout is cleared while already running the sync
if (this.timeoutHandle == 0) return;
// schedule the next run
console.log(
`Next run (${this.name}) will be in ${dayjs()
.add(this.intervalMs, "milliseconds")
.fromNow()}...`
);
this.timeoutHandle = setTimeout(
this.loop.bind(this, nextArgs),
this.intervalMs
);
});
return this;
}
stop() {
clearTimeout(this.timeoutHandle);
}
}