Skip to content

Commit 8dd98a0

Browse files
authored
Merge pull request #177 from nut-tree/fix/174/waitFor-does-not-properly-cancel
(#174) Cancel interval timer creation
2 parents 5a82e71 + fd85acb commit 8dd98a0

File tree

2 files changed

+59
-31
lines changed

2 files changed

+59
-31
lines changed

Diff for: lib/util/poll-action.function.spec.ts

+24
Original file line numberDiff line numberDiff line change
@@ -118,4 +118,28 @@ describe("poll-action", () => {
118118
expect(action).toBeCalledTimes(1);
119119
expect((end - start)).toBeLessThan(updateInterval);
120120
});
121+
122+
it("should fail if action does not resolve within timeout", async () => {
123+
// GIVEN
124+
const updateInterval = 100;
125+
const maxDuration = 200;
126+
const action = jest.fn(() => {
127+
return new Promise((_, reject) => {
128+
setTimeout(() => reject(), 300);
129+
})
130+
});
131+
132+
// WHEN
133+
const start = Date.now();
134+
try {
135+
await timeout(updateInterval, maxDuration, action);
136+
} catch (e) {
137+
expect(e).toEqual(`Action timed out after ${maxDuration} ms`);
138+
}
139+
const end = Date.now();
140+
141+
// THEN
142+
expect(action).toBeCalledTimes(1);
143+
expect((end - start)).toBeGreaterThanOrEqual(maxDuration);
144+
});
121145
});

Diff for: lib/util/poll-action.function.ts

+35-31
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,45 @@
11
export function timeout<R>(updateIntervalMs: number, maxDurationMs: number, action: (...params: any) => Promise<R>): Promise<R> {
22
return new Promise<R>((resolve, reject) => {
33
let interval: NodeJS.Timeout;
4-
const maxTimeout = setTimeout(
5-
() => {
6-
clearTimeout(maxTimeout);
7-
if (interval) {
8-
clearTimeout(interval);
9-
}
10-
reject(`Action timed out after ${maxDurationMs} ms`);
11-
},
12-
maxDurationMs
13-
);
14-
const startInterval = () => {
15-
interval = setTimeout(function intervalFunc() {
16-
action().then((result) => {
17-
if (!result) {
18-
interval = setTimeout(intervalFunc, updateIntervalMs);
19-
} else {
20-
clearTimeout(maxTimeout);
21-
clearTimeout(interval);
22-
resolve(result);
23-
}
24-
}).catch(() => {
25-
interval = setTimeout(intervalFunc, updateIntervalMs);
26-
});
27-
}, updateIntervalMs);
28-
};
4+
let timerCleaned = false
5+
6+
function executeInterval() {
7+
action().then(validateResult).catch(handleRejection);
8+
}
299

30-
action().then((result) => {
10+
function validateResult(result: R){
3111
if (!result) {
32-
startInterval();
12+
interval = setTimeout(executeInterval, updateIntervalMs);
3313
} else {
34-
clearTimeout(maxTimeout);
14+
cleanupTimer();
3515
resolve(result);
3616
}
37-
}).catch(() => {
38-
startInterval();
39-
});
17+
}
18+
19+
function handleRejection() {
20+
if(!timerCleaned){
21+
interval = setTimeout(executeInterval, updateIntervalMs);
22+
}
23+
}
24+
25+
function cleanupTimer(){
26+
timerCleaned = true
27+
if(maxTimeout){
28+
clearTimeout(maxTimeout);
29+
}
30+
if(interval){
31+
clearTimeout(interval);
32+
}
33+
}
34+
35+
const maxTimeout = setTimeout(
36+
() => {
37+
cleanupTimer();
38+
reject(`Action timed out after ${maxDurationMs} ms`);
39+
},
40+
maxDurationMs
41+
);
42+
43+
executeInterval()
4044
});
4145
}

0 commit comments

Comments
 (0)