Skip to content

Commit 14215ce

Browse files
author
Alex Birdsall
committed
Improve comment and type signature
1 parent cd9e7fc commit 14215ce

File tree

1 file changed

+20
-9
lines changed

1 file changed

+20
-9
lines changed
Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,31 @@
1-
import { timer, delay, from, concatMap, takeWhile, last, raceWith, lastValueFrom, NEVER } from "rxjs";
1+
import { concatMap, delay, from, last, lastValueFrom, raceWith, takeWhile, timer, NEVER } from "rxjs";
22

3-
// Known issues:
4-
// - the case where `apiFn` returns `false` and `condition(false) === true` is impossible to distinguish from a timeout
3+
/**
4+
* Repeatedly calls `apiFn` every `interval` milliseconds, until either `conditionFn`
5+
* returns `true` or `options.maxTimeout` milliseconds have elapsed. Returns a Promise
6+
* which resolves to `false` if `options.maxTimout` is reached or the value of `apiFn`
7+
* which passes the condition otherwise. If no `options.maxTimeout` is specified, it will
8+
* continue polling indefinitely until a matching value is found, so let's try not to DDOS
9+
* ourselves.
10+
*
11+
* Known issues:
12+
* - the case where `apiFn` returns `false` and `conditionFn(false) === true` is impossible
13+
* to distinguish from a timeout, so don't poll for a boolean without first wrapping it
14+
* with something like `.then(bool => ({ hopefullyUsefulFieldName: bool }))`.
15+
*/
516
export function pollUntil<ResponseType>(
617
apiFn: () => Promise<ResponseType>,
7-
condition: (res: ResponseType) => boolean,
18+
conditionFn: (res: ResponseType) => boolean,
819
options: { interval: number; maxTimeout?: number }
9-
) {
20+
): Promise<ResponseType | false> {
1021
const { interval, maxTimeout } = options;
1122
const poll$ = timer(0, interval).pipe(
12-
concatMap((_) => from(apiFn())),
13-
takeWhile((result) => !condition(result), true),
14-
last()
23+
concatMap((_) => from(apiFn())), // combine all emitted values into a single stream
24+
takeWhile((result) => !conditionFn(result), true),
25+
last() // only emit the latest polled value
1526
);
1627

17-
const timeout$ = maxTimeout ? from([false]).pipe(delay(maxTimeout)) : NEVER;
28+
const timeout$ = maxTimeout ? from([false] as Array<false>).pipe(delay(maxTimeout)) : NEVER;
1829

1930
return lastValueFrom(poll$.pipe(raceWith(timeout$)));
2031
}

0 commit comments

Comments
 (0)