Skip to content

Commit

Permalink
fix(first): will now only emit one value in recursive cases
Browse files Browse the repository at this point in the history
adds guard after first emitted value to prevent reentrant behavior

fixes #2098
  • Loading branch information
benlesh committed Nov 5, 2016
1 parent 39214f2 commit 80ca01d
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 3 deletions.
14 changes: 14 additions & 0 deletions spec/operators/first-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,20 @@ describe('Observable.prototype.first', () => {
expectSubscriptions(e1.subscriptions).toBe(sub);
});

it('should only emit one value in recursive cases', () => {
const subject = new Rx.Subject<number>();
const results = [];

subject.first().subscribe(x => {
results.push(x);
subject.next(x + 1);
});

subject.next(0);

expect(results).to.deep.equal([0]);
});

it('should propagate error from the source observable', () => {
const e1 = hot('---^---#');
const expected = '----#';
Expand Down
10 changes: 7 additions & 3 deletions src/operator/first.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ class FirstOperator<T, R> implements Operator<T, R> {
class FirstSubscriber<T, R> extends Subscriber<T> {
private index: number = 0;
private hasCompleted: boolean = false;
private _emitted: boolean = false;

constructor(destination: Subscriber<R>,
private predicate?: (value: T, index: number, source: Observable<T>) => boolean,
Expand Down Expand Up @@ -137,9 +138,12 @@ class FirstSubscriber<T, R> extends Subscriber<T> {

private _emitFinal(value: any) {
const destination = this.destination;
destination.next(value);
destination.complete();
this.hasCompleted = true;
if (!this._emitted) {
this._emitted = true;
destination.next(value);
destination.complete();
this.hasCompleted = true;
}
}

protected _complete(): void {
Expand Down

0 comments on commit 80ca01d

Please sign in to comment.