From c919c684ad63724f0b55ccc4561f847773d945c8 Mon Sep 17 00:00:00 2001 From: Nicholas Jamieson Date: Sun, 25 Oct 2020 16:30:51 +1000 Subject: [PATCH] fix(debounce): don't signal on complete BREAKING CHANGE: the observable returned by the debounce operator's duration selector must emit a next notification to end the duration. Complete notifications no longer end the duration. --- spec/operators/debounce-spec.ts | 58 +++++++++++++++--------------- src/internal/operators/debounce.ts | 6 ++-- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/spec/operators/debounce-spec.ts b/spec/operators/debounce-spec.ts index c6ae33eebf..bb86033e55 100644 --- a/spec/operators/debounce-spec.ts +++ b/spec/operators/debounce-spec.ts @@ -20,7 +20,7 @@ describe('debounce', () => { it('should debounce values by a specified cold Observable', () => { testScheduler.run(({ cold, hot, expectObservable }) => { const e1 = hot(' -a--bc--d---|'); - const e2 = cold(' --| '); + const e2 = cold(' --x '); const expected = '---a---c--d-|'; const result = e1.pipe(debounce(() => e2)); @@ -364,11 +364,11 @@ describe('debounce', () => { }); }); - it('should mirror the source when given an empty selector Observable', () => { + it('should ignore all values except last, when given an empty selector Observable', () => { testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => { - const e1 = hot(' --------a-x-yz---bxy---z--c--x--y--z|'); - const e1subs = ' ^-----------------------------------!'; - const expected = '--------a-x-yz---bxy---z--c--x--y--z|'; + const e1 = hot(' --------a-x-yz---bxy---z--c--x--y--z| '); + const e1subs = ' ^-----------------------------------! '; + const expected = '------------------------------------(z|)'; function selectorFunction(x: string) { return EMPTY; @@ -394,20 +394,20 @@ describe('debounce', () => { }); }); - it('should delay element by selector observable completes when it does not emits', () => { + it('should not delay by selector observable completes when it does not emits', () => { testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const e1 = hot(' --------a--------b--------c---------|'); - const e1subs = ' ^-----------------------------------!'; - const expected = '---------a---------b---------c------|'; + const e1 = hot(' --------a--------b--------c---------| '); + const e1subs = ' ^-----------------------------------! '; + const expected = '------------------------------------(c|)'; const selector = [ - cold(' -| '), - cold(' --| '), - cold(' ---| '), + cold(' -| '), + cold(' --| '), + cold(' ---| '), ]; const selectorSubs = [ - ' --------^! ', - ' -----------------^-! ', - ' --------------------------^--! ', + ' --------^! ', + ' -----------------^-! ', + ' --------------------------^--! ', ]; expectObservable(e1.pipe(debounce(() => selector.shift()!))).toBe(expected); @@ -418,24 +418,24 @@ describe('debounce', () => { }); }); - it('should debounce by selector observable completes when it does not emits', () => { + it('should not debounce by selector observable completes when it does not emits', () => { testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { - const e1 = hot(' ----a--b-c---------de-------------|'); - const e1subs = ' ^---------------------------------!'; - const expected = '-----a------c------------e--------|'; + const e1 = hot(' ----a--b-c---------de-------------| '); + const e1subs = ' ^---------------------------------! '; + const expected = '----------------------------------(e|)'; const selector = [ - cold(' -| '), - cold(' --| '), - cold(' ---| '), - cold(' ----| '), - cold(' -----| '), + cold(' -| '), + cold(' --| '), + cold(' ---| '), + cold(' ----| '), + cold(' -----| '), ]; const selectorSubs = [ - ' ----^! ', - ' -------^-! ', - ' ---------^--! ', - ' -------------------^! ', - ' --------------------^----! ', + ' ----^! ', + ' -------^-! ', + ' ---------^--! ', + ' -------------------^! ', + ' --------------------^----! ', ]; expectObservable(e1.pipe(debounce(() => selector.shift()!))).toBe(expected); diff --git a/src/internal/operators/debounce.ts b/src/internal/operators/debounce.ts index 4d6e5b23fb..c4bc0589af 100644 --- a/src/internal/operators/debounce.ts +++ b/src/internal/operators/debounce.ts @@ -1,8 +1,8 @@ /** @prettier */ import { Subscriber } from '../Subscriber'; import { MonoTypeOperatorFunction, ObservableInput } from '../types'; - import { operate } from '../util/lift'; +import { noop } from '../util/noop'; import { OperatorSubscriber } from './OperatorSubscriber'; import { innerFrom } from '../observable/from'; @@ -20,7 +20,7 @@ import { innerFrom } from '../observable/from'; * This operator keeps track of the most recent notification from the source * Observable, and spawns a duration Observable by calling the * `durationSelector` function. The notification is emitted only when the duration - * Observable emits a notification or completes, and if no other notification was emitted on + * Observable emits a next notification, and if no other notification was emitted on * the source Observable since the duration Observable was spawned. If a new * notification appears before the duration Observable emits, the previous notification will * not be emitted and a new duration is scheduled from `durationSelector` is scheduled. @@ -97,7 +97,7 @@ export function debounce(durationSelector: (value: T) => ObservableInput lastValue = value; // Capture our duration subscriber, so we can unsubscribe it when we're notified // and we're going to emit the value. - durationSubscriber = new OperatorSubscriber(subscriber, emit, undefined, emit); + durationSubscriber = new OperatorSubscriber(subscriber, emit, undefined, noop); // Subscribe to the duration. innerFrom(durationSelector(value)).subscribe(durationSubscriber); },