/
start.ts
101 lines (97 loc) · 2.8 KB
/
start.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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import {$A, $S, IterationState, Operation} from '../types';
import {isPromiseLike} from '../typeguards';
import {createOperation} from '../utils';
/**
* @deprecated
* Use {@link skipUntil} instead (`start` will be removed in v3.0.0).
*
* Starts emitting values, once the predicate test passes.
*
* ```ts
* import {pipe, start} from 'iter-ops';
*
* const i = pipe(
* [1, 2, 3, 4, 5, 6, 7, 8, 9],
* start(a => a === 5) // start emitting when 5 is encountered
* );
*
* console.log(...i); //=> 5, 6, 7, 8, 9
* ```
*
* Note that the predicate can only return a `Promise` inside an asynchronous pipeline,
* or else the `Promise` will be treated as a truthy value.
*
* @see
* - {@link stop}
* - {@link skipUntil}
*
* @category Sync+Async
*/
export function start<T>(
cb: (
value: T,
index: number,
state: IterationState
) => boolean | Promise<boolean>
): Operation<T, T>;
export function start(...args: unknown[]) {
return createOperation(startSync, startAsync, args);
}
function startSync<T>(
iterable: Iterable<T>,
cb: (value: T, index: number, state: IterationState) => boolean
): Iterable<T> {
return {
[$S](): Iterator<T> {
const i = iterable[$S]();
const state: IterationState = {};
let index = 0,
started: boolean;
return {
next(): IteratorResult<T> {
let a = i.next();
if (!started) {
while (!a.done && !cb(a.value, index++, state)) {
a = i.next();
}
started = true;
}
return a;
},
};
},
};
}
function startAsync<T>(
iterable: AsyncIterable<T>,
cb: (
value: T,
index: number,
state: IterationState
) => boolean | Promise<boolean>
): AsyncIterable<T> {
return {
[$A](): AsyncIterator<T> {
const i = iterable[$A]();
const state: IterationState = {};
let index = 0,
started: boolean;
return {
next(): Promise<IteratorResult<T>> {
return i.next().then((a) => {
if (started) {
return a;
}
const r = (a.done ||
cb(a.value, index++, state)) as Promise<boolean>;
const out = (flag: any) => {
started = flag;
return started ? a : this.next();
};
return isPromiseLike(r) ? r.then(out) : out(r);
});
},
};
},
};
}