Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 4a03704

Browse files
authored
fix(async-utils): prevent timeout and interval checks in wait from leaving open handles (#682)
* fix(async-utils): prevent timeout and interval checks in wait from leaving open handles * refactor(async-utils): rename timeoutSignal to timeoutController
1 parent b869640 commit 4a03704

File tree

3 files changed

+50
-32
lines changed

3 files changed

+50
-32
lines changed

‎src/core/asyncUtils.ts

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
AsyncUtils
88
} from '../types'
99

10-
import { resolveAfter,callAfter} from '../helpers/promises'
10+
import { createTimeoutController} from '../helpers/createTimeoutController'
1111
import { TimeoutError } from '../helpers/error'
1212

1313
const DEFAULT_INTERVAL = 50
@@ -20,37 +20,26 @@ function asyncUtils(act: Act, addResolver: (callback: () => void) => void): Asyn
2020
return callbackResult ?? callbackResult === undefined
2121
}
2222

23+
const timeoutSignal = createTimeoutController(timeout)
24+
2325
const waitForResult = async () => {
2426
while (true) {
25-
await Promise.race(
26-
[
27-
new Promise<void>((resolve) => addResolver(resolve)),
28-
interval && resolveAfter(interval)
29-
].filter(Boolean)
30-
)
31-
32-
if (checkResult()) {
27+
const intervalSignal = createTimeoutController(interval)
28+
timeoutSignal.onTimeout(() => intervalSignal.cancel())
29+
30+
await intervalSignal.wrap(new Promise<void>(addResolver))
31+
32+
if (checkResult() || timeoutSignal.timedOut) {
3333
return
3434
}
3535
}
3636
}
3737

38-
let timedOut = false
39-
4038
if (!checkResult()) {
41-
if (timeout) {
42-
const timeoutPromise = () =>
43-
callAfter(() => {
44-
timedOut = true
45-
}, timeout)
46-
47-
await act(() => Promise.race([waitForResult(), timeoutPromise()]))
48-
} else {
49-
await act(waitForResult)
50-
}
39+
await act(() => timeoutSignal.wrap(waitForResult()))
5140
}
5241

53-
return !timedOut
42+
return !timeoutSignal.timedOut
5443
}
5544

5645
const waitFor = async (

‎src/helpers/createTimeoutController.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { WaitOptions } from '../types'
2+
3+
function createTimeoutController(timeout: WaitOptions['timeout']) {
4+
let timeoutId: NodeJS.Timeout
5+
const timeoutCallbacks: Array<() => void> = []
6+
7+
const timeoutController = {
8+
onTimeout(callback: () => void) {
9+
timeoutCallbacks.push(callback)
10+
},
11+
wrap(promise: Promise<void>) {
12+
return new Promise<void>((resolve, reject) => {
13+
timeoutController.timedOut = false
14+
timeoutController.onTimeout(resolve)
15+
16+
if (timeout) {
17+
timeoutId = setTimeout(() => {
18+
timeoutController.timedOut = true
19+
timeoutCallbacks.forEach((callback) => callback())
20+
resolve()
21+
}, timeout)
22+
}
23+
24+
promise
25+
.then(resolve)
26+
.catch(reject)
27+
.finally(() => timeoutController.cancel())
28+
})
29+
},
30+
cancel() {
31+
clearTimeout(timeoutId)
32+
},
33+
timedOut: false
34+
}
35+
36+
return timeoutController
37+
}
38+
39+
export { createTimeoutController }

‎src/helpers/promises.ts

Lines changed: 0 additions & 10 deletions
This file was deleted.

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /