From 73eb6582b50244088406547a7a65e5937accfe2e Mon Sep 17 00:00:00 2001 From: OJ Kwon Date: Tue, 1 Mar 2016 13:27:33 -0800 Subject: [PATCH] fix(takeLast): fix takeLast behavior to emit correct order closes #1407 --- spec/operators/takeLast-spec.ts | 34 +++++++++++++++++++++++++ src/operator/takeLast.ts | 44 ++++++++++++--------------------- 2 files changed, 50 insertions(+), 28 deletions(-) diff --git a/spec/operators/takeLast-spec.ts b/spec/operators/takeLast-spec.ts index a192221250..19f2fdb64c 100644 --- a/spec/operators/takeLast-spec.ts +++ b/spec/operators/takeLast-spec.ts @@ -14,6 +14,40 @@ describe('Observable.prototype.takeLast()', () => { expectSubscriptions(e1.subscriptions).toBe(e1subs); }); + it('should take last three values', () => { + const e1 = cold('--a-----b----c---d--| '); + const e1subs = '^ ! '; + const expected = '--------------------(bcd|)'; + + expectObservable(e1.takeLast(3)).toBe(expected); + expectSubscriptions(e1.subscriptions).toBe(e1subs); + }); + + it('should take all element when try to take larger then source', () => { + const e1 = cold('--a-----b----c---d--| '); + const e1subs = '^ ! '; + const expected = '--------------------(abcd|)'; + + expectObservable(e1.takeLast(5)).toBe(expected); + expectSubscriptions(e1.subscriptions).toBe(e1subs); + }); + + it('should take all element when try to take exact', () => { + const e1 = cold('--a-----b----c---d--| '); + const e1subs = '^ ! '; + const expected = '--------------------(abcd|)'; + + expectObservable(e1.takeLast(4)).toBe(expected); + expectSubscriptions(e1.subscriptions).toBe(e1subs); + }); + + 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 5246adc01d..b02e5dee78 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(); } }