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

BehaviorSubject.getValue() always returns initial value if subscribed to observable from Webpack library #5105

Closed
es-repo opened this issue Oct 22, 2019 · 9 comments · Fixed by #6524
Labels
bug Confirmed bug

Comments

@es-repo
Copy link

es-repo commented Oct 22, 2019

Bug Report

Current Behavior

BehaviorSubject.getValue() always returns initial value if subscribed to an observable from Webpack library while the observable is emitting new values.

Reproduction

-Minimum code which reproduces bug:
https://github.com/es-repo/bug-repro/tree/master/rxjs/behavior-subject-and-observable-from-lib

Run "npm start" from within the "app" folder or open this link https://es-repo.github.io/bug-repro/rxjs/behavior-subject-and-observable-from-lib/app/dist/. And open console.

Code from the "app" which reproduces the issue:

import { BehaviorSubject, interval } from 'rxjs';
import createObservable from 'lib';

const subject1 = new BehaviorSubject(undefined);
createObservable().subscribe(subject1);

const subject2 = new BehaviorSubject(undefined);
interval(1000).subscribe(subject2);

subject1.subscribe(v => {
  console.log(`Observable from lib: value=${v} getValue()=${subject1.getValue()}`);
});

subject2.subscribe(v => {
  console.log(`Observable from app: value=${v} getValue()=${subject2.getValue()}`);
});

Code from the "lib":

import { interval } from 'rxjs';

export default function createObservable() {
  return interval(1000);
}

Console output:

Observable from lib: value=undefined getValue()=undefined
Observable from app: value=undefined getValue()=undefined
Observable from lib: value=0 getValue()=undefined
Observable from app: value=0 getValue()=0
Observable from lib: value=1 getValue()=undefined
Observable from app: value=1 getValue()=1
...

Expected behavior

BehaviorSubject.getValue() should return last value emitted from Observable.

Environment

  • Runtime: Node v12.7.0, Chrome v78
  • RxJS version: 6.5.3
  • Webpack: 4.41.2

Additional context

Related issue: #5051

@samal-rasmussen
Copy link
Contributor

Hi es-repo. I made a pull request to your reproduction that adds a working example that uses an app local source.

@es-repo
Copy link
Author

es-repo commented Oct 24, 2019

Thanks, samal!

@Stradivario
Copy link

Stradivario commented Dec 21, 2019

Who use to subscribe with other observable ?

const subject2 = new BehaviorSubject(undefined);
interval(1000).subscribe(subject2);

I don't think this is a correct usage and even i don't know what will happen that way passing observable directly as a subscription.

const subject2 = new BehaviorSubject(undefined);
interval(1000).pipe(mergeMap(() => subject2)).subscribe(console.log)
subject2.next(true)

@es-repo
Copy link
Author

es-repo commented Dec 23, 2019

Who use to subscribe with other observable ?

const subject2 = new BehaviorSubject(undefined);
interval(1000).subscribe(subject2);

@Stradivario sorry, could you elaborate what do you mean?
observable.subscribe(subject) is how you convert unicast observable into multicast. Or, in another way, subject is both an observable and an observer and as an observer it can be subscribed to observable. What's wrong here from your point of you?

@Stradivario
Copy link

Stradivario commented Dec 24, 2019

Who use to subscribe with other observable ?

const subject2 = new BehaviorSubject(undefined);
interval(1000).subscribe(subject2);

@Stradivario sorry, could you elaborate what do you mean?
observable.subscribe(subject) is how you convert unicast observable into multicast. Or, in another way, subject is both an observable and an observer and as an observer it can be subscribed to observable. What's wrong here from your point of you?

Never seen such a composition of observables i am really sorry if i miss understood it. I just prefer different approach of composing with pipe. My subscribe method is the last thing that i will write even i try to not write subscribe in my code. That's a different scenario and mind set which doesn't belong to me and i will try to get the best from it.

Regards and Merry Christmas,
Kristiyan Tachev

@cartant cartant added the bug Confirmed bug label Jan 25, 2020
cartant added a commit to cartant/rxjs that referenced this issue Jan 25, 2020
cartant added a commit to cartant/rxjs that referenced this issue Jan 25, 2020
@cartant
Copy link
Collaborator

cartant commented Jan 25, 2020

This is a bug, but it cannot easily be fixed. The problem is that the subject isn't seen as a safe/trusted subscriber because the interop source won't see the per-package Symbol that identifies the subject as trusted.

And that means that the subject will be 'cloned' so that an unsubscribe method can be added to it:

context = Object.create(observerOrNext);
if (isFunction(context.unsubscribe)) {
this.add(<() => void> context.unsubscribe.bind(context));
}
context.unsubscribe = this.unsubscribe.bind(this);

And that means the the subject's original state will remain unchanged - the bug you reported.

benlesh pushed a commit that referenced this issue Jan 27, 2020
* test: add failing test for #5105

* chore: skip test and add a comment

* chore: kick CI ... yet again
kwonoj pushed a commit to kwonoj/rxjs that referenced this issue Feb 5, 2020
* test: add failing test for ReactiveX#5105

* chore: skip test and add a comment

* chore: kick CI ... yet again
martinsik pushed a commit to martinsik/rxjs that referenced this issue Feb 15, 2020
* test: add failing test for ReactiveX#5105

* chore: skip test and add a comment

* chore: kick CI ... yet again
tomachalek added a commit to tomachalek/wag that referenced this issue Jun 19, 2020
(methods we cannot use anyway
see ReactiveX/rxjs#5105 vs.
kombo's old getState())
@ccjmne
Copy link
Contributor

ccjmne commented Jul 1, 2020

Is there any way to work around it —while still transpiling w/ Webpack— without resorting to using another kind of Subject?

@benlesh
Copy link
Member

benlesh commented Jul 2, 2020

@cartant isn't this handled now in the beta version?

@cartant
Copy link
Collaborator

cartant commented Jul 2, 2020

@benlesh It's quite likely that #5472 fixes it, but that was merged only about 3 weeks ago, so it's probably not in the published beta - I cannot remember the date it was published. I didn't have this issue in mind when I made that fix, but 🤞

benlesh added a commit to benlesh/rxjs that referenced this issue Jul 14, 2021
benlesh added a commit that referenced this issue Jul 21, 2021
* chore: Stop skipping valid test

Resolves #5105

* chore: Add comment about why this test is skipped.

* chore: Correct skipped tests

- Some of the skipped tests were clearly copied from retryWhen but never updated appropriately.
- One of the skipped tests showed a buggy behavior that is now reported in an issue and a comment with a link to that issue is now above it.

* chore: Update skipped tests

- Uncomments a skipped test that was fixed with the v7 refactor (apparently just via better architecture)
- Adds an additional test to simplify the same assertion
- Adds a comment above a skipped section of tests explaining that we can probably remove them in v8 after we've moved completely to newer multicasting paradigms and removed deprecated operators.

Resolves #5370

* chore: Stops skipping a fixed test.

* chore: Add commented out bit to help find skipped tests

Figuring out what tests are skipped out of 3,000+ tests is pretty annoying. I want to leave this here as a sign post to help.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Confirmed bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants