Skip to content

Commit

Permalink
feat(repeat): add higher-order lettable version of repeat
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonaden committed Sep 6, 2017
1 parent 76668a9 commit 8473fe5
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 44 deletions.
47 changes: 3 additions & 44 deletions src/operator/repeat.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { Operator } from '../Operator';
import { Subscriber } from '../Subscriber';

import { Observable } from '../Observable';
import { EmptyObservable } from '../observable/EmptyObservable';
import { TeardownLogic } from '../Subscription';
import { repeat as higherOrder } from '../operators/repeat';

/**
* Returns an Observable that repeats the stream of items emitted by the source Observable at most count times.
Expand All @@ -17,44 +15,5 @@ import { TeardownLogic } from '../Subscription';
* @owner Observable
*/
export function repeat<T>(this: Observable<T>, count: number = -1): Observable<T> {
if (count === 0) {
return new EmptyObservable<T>();
} else if (count < 0) {
return this.lift(new RepeatOperator(-1, this));
} else {
return this.lift(new RepeatOperator(count - 1, this));
}
}

class RepeatOperator<T> implements Operator<T, T> {
constructor(private count: number,
private source: Observable<T>) {
}
call(subscriber: Subscriber<T>, source: any): TeardownLogic {
return source.subscribe(new RepeatSubscriber(subscriber, this.count, this.source));
}
}

/**
* We need this JSDoc comment for affecting ESDoc.
* @ignore
* @extends {Ignored}
*/
class RepeatSubscriber<T> extends Subscriber<T> {
constructor(destination: Subscriber<any>,
private count: number,
private source: Observable<T>) {
super(destination);
}
complete() {
if (!this.isStopped) {
const { source, count } = this;
if (count === 0) {
return super.complete();
} else if (count > -1) {
this.count = count - 1;
}
source.subscribe(this._unsubscribeAndRecycle());
}
}
return higherOrder(count)(this);
}
1 change: 1 addition & 0 deletions src/operators/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export { publish } from './publish';
export { publishBehavior } from './publishBehavior';
export { race } from './race';
export { reduce } from './reduce';
export { repeat } from './repeat';
export { refCount } from './refCount';
export { scan } from './scan';
export { subscribeOn } from './subscribeOn';
Expand Down
63 changes: 63 additions & 0 deletions src/operators/repeat.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { Operator } from '../Operator';
import { Subscriber } from '../Subscriber';
import { Observable } from '../Observable';
import { EmptyObservable } from '../observable/EmptyObservable';
import { TeardownLogic } from '../Subscription';
import { MonoTypeOperatorFunction } from '../interfaces';

/**
* Returns an Observable that repeats the stream of items emitted by the source Observable at most count times.
*
* <img src="./img/repeat.png" width="100%">
*
* @param {number} [count] The number of times the source Observable items are repeated, a count of 0 will yield
* an empty Observable.
* @return {Observable} An Observable that repeats the stream of items emitted by the source Observable at most
* count times.
* @method repeat
* @owner Observable
*/
export function repeat<T>(count: number = -1): MonoTypeOperatorFunction<T> {
return (source: Observable<T>) => {
if (count === 0) {
return new EmptyObservable<T>();
} else if (count < 0) {
return source.lift(new RepeatOperator(-1, source));
} else {
return source.lift(new RepeatOperator(count - 1, source));
}
};
}

class RepeatOperator<T> implements Operator<T, T> {
constructor(private count: number,
private source: Observable<T>) {
}
call(subscriber: Subscriber<T>, source: any): TeardownLogic {
return source.subscribe(new RepeatSubscriber(subscriber, this.count, this.source));
}
}

/**
* We need this JSDoc comment for affecting ESDoc.
* @ignore
* @extends {Ignored}
*/
class RepeatSubscriber<T> extends Subscriber<T> {
constructor(destination: Subscriber<any>,
private count: number,
private source: Observable<T>) {
super(destination);
}
complete() {
if (!this.isStopped) {
const { source, count } = this;
if (count === 0) {
return super.complete();
} else if (count > -1) {
this.count = count - 1;
}
source.subscribe(this._unsubscribeAndRecycle());
}
}
}

0 comments on commit 8473fe5

Please sign in to comment.