Skip to content

Commit f86c862

Browse files
committed
feat(takeWhile): add higher-order lettable version of takeWhile
1 parent bb2ddaa commit f86c862

File tree

3 files changed

+92
-48
lines changed

3 files changed

+92
-48
lines changed

src/operator/takeWhile.ts

Lines changed: 2 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
import { Operator } from '../Operator';
21
import { Observable } from '../Observable';
3-
import { Subscriber } from '../Subscriber';
4-
import { TeardownLogic } from '../Subscription';
2+
import { takeWhile as higherOrder } from '../operators/takeWhile';
53

64
/**
75
* Emits values emitted by the source Observable so long as each value satisfies
@@ -40,49 +38,5 @@ import { TeardownLogic } from '../Subscription';
4038
* @owner Observable
4139
*/
4240
export function takeWhile<T>(this: Observable<T>, predicate: (value: T, index: number) => boolean): Observable<T> {
43-
return this.lift(new TakeWhileOperator(predicate));
44-
}
45-
46-
class TakeWhileOperator<T> implements Operator<T, T> {
47-
constructor(private predicate: (value: T, index: number) => boolean) {
48-
}
49-
50-
call(subscriber: Subscriber<T>, source: any): TeardownLogic {
51-
return source.subscribe(new TakeWhileSubscriber(subscriber, this.predicate));
52-
}
53-
}
54-
55-
/**
56-
* We need this JSDoc comment for affecting ESDoc.
57-
* @ignore
58-
* @extends {Ignored}
59-
*/
60-
class TakeWhileSubscriber<T> extends Subscriber<T> {
61-
private index: number = 0;
62-
63-
constructor(destination: Subscriber<T>,
64-
private predicate: (value: T, index: number) => boolean) {
65-
super(destination);
66-
}
67-
68-
protected _next(value: T): void {
69-
const destination = this.destination;
70-
let result: boolean;
71-
try {
72-
result = this.predicate(value, this.index++);
73-
} catch (err) {
74-
destination.error(err);
75-
return;
76-
}
77-
this.nextOrComplete(value, result);
78-
}
79-
80-
private nextOrComplete(value: T, predicateResult: boolean): void {
81-
const destination = this.destination;
82-
if (Boolean(predicateResult)) {
83-
destination.next(value);
84-
} else {
85-
destination.complete();
86-
}
87-
}
41+
return higherOrder(predicate)(this);
8842
}

src/operators/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ export { switchMapTo } from './switchMapTo';
7272
export { take } from './take';
7373
export { takeLast } from './takeLast';
7474
export { takeUntil } from './takeUntil';
75+
export { takeWhile } from './takeWhile';
7576
export { tap } from './tap';
7677
export { timestamp } from './timestamp';
7778
export { toArray } from './toArray';

src/operators/takeWhile.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { Operator } from '../Operator';
2+
import { Observable } from '../Observable';
3+
import { Subscriber } from '../Subscriber';
4+
import { TeardownLogic } from '../Subscription';
5+
import { MonoTypeOperatorFunction } from '../interfaces';
6+
7+
/**
8+
* Emits values emitted by the source Observable so long as each value satisfies
9+
* the given `predicate`, and then completes as soon as this `predicate` is not
10+
* satisfied.
11+
*
12+
* <span class="informal">Takes values from the source only while they pass the
13+
* condition given. When the first value does not satisfy, it completes.</span>
14+
*
15+
* <img src="./img/takeWhile.png" width="100%">
16+
*
17+
* `takeWhile` subscribes and begins mirroring the source Observable. Each value
18+
* emitted on the source is given to the `predicate` function which returns a
19+
* boolean, representing a condition to be satisfied by the source values. The
20+
* output Observable emits the source values until such time as the `predicate`
21+
* returns false, at which point `takeWhile` stops mirroring the source
22+
* Observable and completes the output Observable.
23+
*
24+
* @example <caption>Emit click events only while the clientX property is greater than 200</caption>
25+
* var clicks = Rx.Observable.fromEvent(document, 'click');
26+
* var result = clicks.takeWhile(ev => ev.clientX > 200);
27+
* result.subscribe(x => console.log(x));
28+
*
29+
* @see {@link take}
30+
* @see {@link takeLast}
31+
* @see {@link takeUntil}
32+
* @see {@link skip}
33+
*
34+
* @param {function(value: T, index: number): boolean} predicate A function that
35+
* evaluates a value emitted by the source Observable and returns a boolean.
36+
* Also takes the (zero-based) index as the second argument.
37+
* @return {Observable<T>} An Observable that emits the values from the source
38+
* Observable so long as each value satisfies the condition defined by the
39+
* `predicate`, then completes.
40+
* @method takeWhile
41+
* @owner Observable
42+
*/
43+
export function takeWhile<T>(predicate: (value: T, index: number) => boolean): MonoTypeOperatorFunction<T> {
44+
return (source: Observable<T>) => source.lift(new TakeWhileOperator(predicate));
45+
}
46+
47+
class TakeWhileOperator<T> implements Operator<T, T> {
48+
constructor(private predicate: (value: T, index: number) => boolean) {
49+
}
50+
51+
call(subscriber: Subscriber<T>, source: any): TeardownLogic {
52+
return source.subscribe(new TakeWhileSubscriber(subscriber, this.predicate));
53+
}
54+
}
55+
56+
/**
57+
* We need this JSDoc comment for affecting ESDoc.
58+
* @ignore
59+
* @extends {Ignored}
60+
*/
61+
class TakeWhileSubscriber<T> extends Subscriber<T> {
62+
private index: number = 0;
63+
64+
constructor(destination: Subscriber<T>,
65+
private predicate: (value: T, index: number) => boolean) {
66+
super(destination);
67+
}
68+
69+
protected _next(value: T): void {
70+
const destination = this.destination;
71+
let result: boolean;
72+
try {
73+
result = this.predicate(value, this.index++);
74+
} catch (err) {
75+
destination.error(err);
76+
return;
77+
}
78+
this.nextOrComplete(value, result);
79+
}
80+
81+
private nextOrComplete(value: T, predicateResult: boolean): void {
82+
const destination = this.destination;
83+
if (Boolean(predicateResult)) {
84+
destination.next(value);
85+
} else {
86+
destination.complete();
87+
}
88+
}
89+
}

0 commit comments

Comments
 (0)