Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/gitpod-protocol/src/util/timeout.ts
2500 views
1
/**
2
* Copyright (c) 2024 Gitpod GmbH. All rights reserved.
3
* Licensed under the GNU Affero General Public License (AGPL).
4
* See License.AGPL.txt in the project root for license information.
5
*/
6
7
/**
8
* A restartable timeout, based on an AbortController + setTimeout.
9
*
10
* Note: When cleared/reset, the AbortController is _NOT_ aborted.
11
*/
12
export class Timeout {
13
private _timer: NodeJS.Timeout | undefined;
14
private _abortController: AbortController | undefined;
15
16
/**
17
* @param timeout The timeout in milliseconds.
18
* @param abortCondition An optional condition evaluated on timeout: If set, the abort is only emitted if it evaluates to true.
19
*/
20
constructor(readonly timeout: number, readonly abortCondition?: () => boolean) {}
21
22
/**
23
* Starts a new timeout (and clears the old one). Identical to `reset`.
24
*/
25
public start() {
26
this.restart();
27
}
28
29
/**
30
* Starts a new timeout (and clears the old one).
31
*/
32
public restart() {
33
this.clear();
34
35
const abortController = new AbortController();
36
this._abortController = abortController;
37
if (this.timeout === Infinity) {
38
return;
39
}
40
this._timer = setTimeout(() => {
41
if (this.abortCondition && !this.abortCondition()) {
42
return;
43
}
44
45
abortController.abort();
46
}, this.timeout);
47
}
48
49
/**
50
* Clears the current timeout.
51
*/
52
public clear() {
53
if (this._timer) {
54
clearTimeout(this._timer);
55
this._timer = undefined;
56
}
57
if (this._abortController) {
58
this._abortController = undefined;
59
}
60
}
61
62
/**
63
* Convenience method to await the timeout.
64
* @returns
65
*/
66
public async await(): Promise<boolean> {
67
const abortController = this._abortController;
68
if (!abortController) {
69
return false;
70
}
71
72
return new Promise((resolve) => {
73
abortController.signal.addEventListener("abort", () => resolve(true));
74
});
75
}
76
77
/**
78
* @returns The AbortSignal of the current timeout, if one is active.
79
*/
80
get signal() {
81
return this._abortController?.signal;
82
}
83
}
84
85