diff --git a/spec/operators/takeLast-spec.ts b/spec/operators/takeLast-spec.ts index a1922212502..b892f8da950 100644 --- a/spec/operators/takeLast-spec.ts +++ b/spec/operators/takeLast-spec.ts @@ -1,6 +1,6 @@ import * as Rx from '../../dist/cjs/Rx'; import {hot, cold, expectObservable, expectSubscriptions} from '../helpers/marble-testing'; -import {it, asDiagram} from '../helpers/test-helper'; +import {it, DoneSignature, asDiagram} from '../helpers/test-helper'; const Observable = Rx.Observable; @@ -14,6 +14,46 @@ describe('Observable.prototype.takeLast()', () => { expectSubscriptions(e1.subscriptions).toBe(e1subs); }); + it('should take last three values', (done: DoneSignature) => { + const expected = [2, 3, 4]; + + Observable.of(0, 1, 2, 3, 4).takeLast(3).subscribe((x) => { + expect(x).toBe(expected.shift()); + }, done.fail, () => { + expect(expected.length).toBe(0); + done(); + }); + }); + + it('should take all element when try to take larger then source', (done: DoneSignature) => { + const expected = [0, 1, 2]; + + Observable.of(0, 1, 2).takeLast(5).subscribe((x) => { + expect(x).toBe(expected.shift()); + }, done.fail, () => { + expect(expected.length).toBe(0); + done(); + }); + }); + + it('should take all element when try to take exact', (done: DoneSignature) => { + const expected = [0, 1, 2]; + + Observable.of(0, 1, 2).takeLast(3).subscribe((x) => { + expect(x).toBe(expected.shift()); + }, done.fail, () => { + expect(expected.length).toBe(0); + done(); + }); + }); + + it('should not take any values', () => { + const e1 = cold('--a-----b----c---d--|'); + const expected = '|'; + + expectObservable(e1.takeLast(0)).toBe(expected); + }); + it('should work with empty', () => { const e1 = cold('|'); const e1subs = '(^!)'; diff --git a/src/operator/takeLast.ts b/src/operator/takeLast.ts index 5246adc01d8..b02e5dee782 100644 --- a/src/operator/takeLast.ts +++ b/src/operator/takeLast.ts @@ -29,52 +29,40 @@ class TakeLastOperator implements Operator { } class TakeLastSubscriber extends Subscriber { - private ring: T[]; + private ring: Array = new Array(); private count: number = 0; - private index: number = 0; constructor(destination: Subscriber, private total: number) { super(destination); - this.ring = new Array(total); } protected _next(value: T): void { - - let index = this.index; const ring = this.ring; const total = this.total; - const count = this.count; + const count = this.count++; - if (total > 1) { - if (count < total) { - this.count = count + 1; - this.index = index + 1; - } else if (index === 0) { - this.index = ++index; - } else if (index < total) { - this.index = index + 1; - } else { - this.index = index = 0; - } - } else if (count < total) { - this.count = total; + if (ring.length < total) { + ring.push(value); + } else { + const index = count % total; + ring[index] = value; } - - ring[index] = value; } protected _complete(): void { + const destination = this.destination; + let count = this.count; - let iter = -1; - const { ring, count, total, destination } = this; - let index = (total === 1 || count < total) ? 0 : this.index - 1; + if (count > 0) { + const total = this.count >= this.total ? this.total : this.count; + const ring = this.ring; - while (++iter < count) { - if (iter + index === total) { - index = total - iter; + for (let i = 0; i < total; i++) { + const idx = (count++) % total; + destination.next(ring[idx]); } - destination.next(ring[iter + index]); } + destination.complete(); } }