Skip to content

Commit 8c73e6e

Browse files
committed
feat(sample): add higher-order lettable version of sample
1 parent 1290e3c commit 8c73e6e

File tree

3 files changed

+94
-51
lines changed

3 files changed

+94
-51
lines changed

src/operator/sample.ts

Lines changed: 2 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
1-
import { Operator } from '../Operator';
21
import { Observable } from '../Observable';
3-
import { Subscriber } from '../Subscriber';
4-
import { TeardownLogic } from '../Subscription';
5-
import { OuterSubscriber } from '../OuterSubscriber';
6-
import { InnerSubscriber } from '../InnerSubscriber';
7-
import { subscribeToResult } from '../util/subscribeToResult';
2+
import { sample as higherOrder } from '../operators/sample';
83

94
/**
105
* Emits the most recently emitted value from the source Observable whenever
@@ -41,49 +36,5 @@ import { subscribeToResult } from '../util/subscribeToResult';
4136
* @owner Observable
4237
*/
4338
export function sample<T>(this: Observable<T>, notifier: Observable<any>): Observable<T> {
44-
return this.lift(new SampleOperator(notifier));
45-
}
46-
47-
class SampleOperator<T> implements Operator<T, T> {
48-
constructor(private notifier: Observable<any>) {
49-
}
50-
51-
call(subscriber: Subscriber<T>, source: any): TeardownLogic {
52-
const sampleSubscriber = new SampleSubscriber(subscriber);
53-
const subscription = source.subscribe(sampleSubscriber);
54-
subscription.add(subscribeToResult(sampleSubscriber, this.notifier));
55-
return subscription;
56-
}
57-
}
58-
59-
/**
60-
* We need this JSDoc comment for affecting ESDoc.
61-
* @ignore
62-
* @extends {Ignored}
63-
*/
64-
class SampleSubscriber<T, R> extends OuterSubscriber<T, R> {
65-
private value: T;
66-
private hasValue: boolean = false;
67-
68-
protected _next(value: T) {
69-
this.value = value;
70-
this.hasValue = true;
71-
}
72-
73-
notifyNext(outerValue: T, innerValue: R,
74-
outerIndex: number, innerIndex: number,
75-
innerSub: InnerSubscriber<T, R>): void {
76-
this.emitValue();
77-
}
78-
79-
notifyComplete(): void {
80-
this.emitValue();
81-
}
82-
83-
emitValue() {
84-
if (this.hasValue) {
85-
this.hasValue = false;
86-
this.destination.next(this.value);
87-
}
88-
}
39+
return higherOrder(notifier)(this);
8940
}

src/operators/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ export { repeatWhen } from './repeatWhen';
5858
export { retry } from './retry';
5959
export { retryWhen } from './retryWhen';
6060
export { refCount } from './refCount';
61+
export { sample } from './sample';
6162
export { scan } from './scan';
6263
export { subscribeOn } from './subscribeOn';
6364
export { switchAll } from './switchAll';

src/operators/sample.ts

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import { Operator } from '../Operator';
2+
import { Observable } from '../Observable';
3+
import { Subscriber } from '../Subscriber';
4+
import { TeardownLogic } from '../Subscription';
5+
import { OuterSubscriber } from '../OuterSubscriber';
6+
import { InnerSubscriber } from '../InnerSubscriber';
7+
import { subscribeToResult } from '../util/subscribeToResult';
8+
9+
import { MonoTypeOperatorFunction } from '../interfaces';
10+
11+
/**
12+
* Emits the most recently emitted value from the source Observable whenever
13+
* another Observable, the `notifier`, emits.
14+
*
15+
* <span class="informal">It's like {@link sampleTime}, but samples whenever
16+
* the `notifier` Observable emits something.</span>
17+
*
18+
* <img src="./img/sample.png" width="100%">
19+
*
20+
* Whenever the `notifier` Observable emits a value or completes, `sample`
21+
* looks at the source Observable and emits whichever value it has most recently
22+
* emitted since the previous sampling, unless the source has not emitted
23+
* anything since the previous sampling. The `notifier` is subscribed to as soon
24+
* as the output Observable is subscribed.
25+
*
26+
* @example <caption>On every click, sample the most recent "seconds" timer</caption>
27+
* var seconds = Rx.Observable.interval(1000);
28+
* var clicks = Rx.Observable.fromEvent(document, 'click');
29+
* var result = seconds.sample(clicks);
30+
* result.subscribe(x => console.log(x));
31+
*
32+
* @see {@link audit}
33+
* @see {@link debounce}
34+
* @see {@link sampleTime}
35+
* @see {@link throttle}
36+
*
37+
* @param {Observable<any>} notifier The Observable to use for sampling the
38+
* source Observable.
39+
* @return {Observable<T>} An Observable that emits the results of sampling the
40+
* values emitted by the source Observable whenever the notifier Observable
41+
* emits value or completes.
42+
* @method sample
43+
* @owner Observable
44+
*/
45+
export function sample<T>(notifier: Observable<any>): MonoTypeOperatorFunction<T> {
46+
return (source: Observable<T>) => source.lift(new SampleOperator(notifier));
47+
}
48+
49+
class SampleOperator<T> implements Operator<T, T> {
50+
constructor(private notifier: Observable<any>) {
51+
}
52+
53+
call(subscriber: Subscriber<T>, source: any): TeardownLogic {
54+
const sampleSubscriber = new SampleSubscriber(subscriber);
55+
const subscription = source.subscribe(sampleSubscriber);
56+
subscription.add(subscribeToResult(sampleSubscriber, this.notifier));
57+
return subscription;
58+
}
59+
}
60+
61+
/**
62+
* We need this JSDoc comment for affecting ESDoc.
63+
* @ignore
64+
* @extends {Ignored}
65+
*/
66+
class SampleSubscriber<T, R> extends OuterSubscriber<T, R> {
67+
private value: T;
68+
private hasValue: boolean = false;
69+
70+
protected _next(value: T) {
71+
this.value = value;
72+
this.hasValue = true;
73+
}
74+
75+
notifyNext(outerValue: T, innerValue: R,
76+
outerIndex: number, innerIndex: number,
77+
innerSub: InnerSubscriber<T, R>): void {
78+
this.emitValue();
79+
}
80+
81+
notifyComplete(): void {
82+
this.emitValue();
83+
}
84+
85+
emitValue() {
86+
if (this.hasValue) {
87+
this.hasValue = false;
88+
this.destination.next(this.value);
89+
}
90+
}
91+
}

0 commit comments

Comments
 (0)