Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

debounceTime does not emit #6375

Closed
dpurp opened this issue May 7, 2021 · 7 comments
Closed

debounceTime does not emit #6375

dpurp opened this issue May 7, 2021 · 7 comments

Comments

@dpurp
Copy link

dpurp commented May 7, 2021

found in google3 \cc @leggechr

Bug Report

Current Behavior
debounceTime fails to emit after a given duration

Expected behavior
debounceTime emits after a given duration

Reproduction

  it('debounces time', async () => {
    const duration = 10;
    const source = new Subject<string>();
    const debouncedSource$ = source.pipe(
        debounceTime(duration),
        shareReplay(1),
    );

    source.next('expected value');
    source.next('should not be emitted');
    // jasmine.clock().tick(duration + 1);  // Wait for debounce to happen.

    expect(await firstValueFrom(debouncedSource$)).toEqual('expected value');
  });

https://stackblitz.com/edit/rxjs-k9cnyb?file=index.ts

Environment

  • Runtime: Chrome v90
  • RxJS version: 7
@cartant
Copy link
Collaborator

cartant commented May 7, 2021

IMO, in situations like this - when you see what appears to be a fundamental bug - it's worthwhile to ask "why do the tests pass?"

This is not a bug. It's a misunderstanding. There is no emission because there is no subscription made to the debouncedSource$ until firstValueFrom value is called. That means that the values emitted from source are 'lost', as it has no subscribers.

To see that this is a problem, add debouncedSource$.subscribe().unsubscribe() just before the source.next('expected value'); call. Doing so subscribes to the source and the debounced value is captured in the ReplaySubject within shareReplay.

Also, your expectation is wrong. debounceTime will emit the last value approximately 10 milliseconds after it's received. It won't emit the first value.

It's working as intended.

@cartant cartant closed this as completed May 7, 2021
@dpurp
Copy link
Author

dpurp commented May 7, 2021

Thanks for the guidance, it appears that my reproduction needs some additional work.

As far as what I do know, the tests in google passed before v7, but do not after v7, so my assumption was that there is something unusual amiss (see #6364)

@cartant
Copy link
Collaborator

cartant commented May 7, 2021

It's unfortunate, but the v6/v7 changes document - that was published to the docs site at the time of the release - was not comprehensive. It missed the breaking changes that were listed in the CHANGELOG. Some of those breaking changes related to notifier observables - those used with operators like debounce - and those notifiers now have to emit a value, as their completing not deemed a 'signal'. This won't effect debounceTime, but maybe that's not actually the problem? If some other piece of code is using a notifier that attempts to signal using completion, that would effect behaviour in which the expected thing just does not happen.

Anyway, the somewhat-more-comprehensive changes document is not yet on the site, but you can find it here:

https://github.com/cartant/rxjs/blob/7e093887d6a42338c5b85aeb3274ca0934904370/docs_app/content/6-to-7-change-summary.md#debounce

@leggechr
Copy link
Contributor

leggechr commented May 7, 2021

Could this be an issue with google mode (aka super gross mode?) many of the issues we're seeing are only reproducible in that mode.

@benlesh
Copy link
Member

benlesh commented May 7, 2021

@leggechr the example posted was just something that would never work. Basically, there was a hot observable (a subject) through which values were nexted, but it wasn't subscribed to until after the values were nexted. Meaning no one was listening.

If you do the correct thing in the test code given, it works just fine:

import { Subject, firstValueFrom } from 'rxjs';
import { debounceTime, shareReplay } from 'rxjs/operators';

const duration = 10;
const source = new Subject<string>();
const debouncedSource$ = source.pipe(
  debounceTime(duration),
  shareReplay(1)
);

// Subscribe in here
firstValueFrom(debouncedSource$).then(value => console.log(value));

// *then* send your values
source.next('should not be emitted'); // debounced away
source.next('expected value');
source.complete();

@dpurp
Copy link
Author

dpurp commented May 7, 2021

Sorry everyone for the noise. I got too excited when I "reproduced" the issue, and didn't realize the obvious bug in my own code.

@benlesh
Copy link
Member

benlesh commented May 7, 2021

Happens to everyone.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants