From 9441def9587d6e86ede030f159387a9479195d49 Mon Sep 17 00:00:00 2001 From: Jay Phelps Date: Tue, 15 Nov 2016 16:42:21 -0800 Subject: [PATCH] fix(timeout): Cancels scheduled timeout, if no longer needed fixes #2134 --- src/operator/timeout.ts | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/operator/timeout.ts b/src/operator/timeout.ts index e69c786905..3df4bf1bee 100644 --- a/src/operator/timeout.ts +++ b/src/operator/timeout.ts @@ -5,6 +5,7 @@ import { Subscriber } from '../Subscriber'; import { Scheduler } from '../Scheduler'; import { Observable } from '../Observable'; import { TeardownLogic } from '../Subscription'; +import { Subscription } from '../Subscription'; import { TimeoutError } from '../util/TimeoutError'; /** @@ -46,6 +47,8 @@ class TimeoutOperator implements Operator { class TimeoutSubscriber extends Subscriber { private index: number = 0; private _previousIndex: number = 0; + private action: Subscription = null; + get previousIndex(): number { return this._previousIndex; } @@ -66,18 +69,34 @@ class TimeoutSubscriber extends Subscriber { private static dispatchTimeout(state: any): void { const source = state.subscriber; const currentIndex = state.index; - if (!source.hasCompleted && source.previousIndex === currentIndex) { + if (source.previousIndex === currentIndex) { source.notifyTimeout(); } } private scheduleTimeout(): void { - let currentIndex = this.index; - this.scheduler.schedule(TimeoutSubscriber.dispatchTimeout, this.waitFor, { subscriber: this, index: currentIndex }); + const currentIndex = this.index; + const timeoutState = { subscriber: this, index: currentIndex }; + + this.cancelTimeout(); + this.action = this.scheduler.schedule( + TimeoutSubscriber.dispatchTimeout, this.waitFor, timeoutState + ); + this.add(this.action); + this.index++; this._previousIndex = currentIndex; } + private cancelTimeout(): void { + const { action } = this; + if (action !== null) { + this.remove(action); + action.unsubscribe(); + this.action = null; + } + } + protected _next(value: T): void { this.destination.next(value);