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

Created on 22 Oct 2019  Â·  9Comments  Â·  Source: ReactiveX/rxjs

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

bug

Most helpful comment

@benlesh It's quite likely that https://github.com/ReactiveX/rxjs/pull/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 🤞

All 9 comments

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

Thanks, samal!

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)

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?

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

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:

https://github.com/ReactiveX/rxjs/blob/f8a487617d6eb96b6f702cc1546c0cac59927d4b/src/internal/Subscriber.ts#L189-L193

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

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

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

@benlesh It's quite likely that https://github.com/ReactiveX/rxjs/pull/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 🤞

Was this page helpful?
0 / 5 - 0 ratings

Related issues

LittleFox94 picture LittleFox94  Â·  3Comments

OliverJAsh picture OliverJAsh  Â·  3Comments

dooreelko picture dooreelko  Â·  3Comments

matthewwithanm picture matthewwithanm  Â·  4Comments

unao picture unao  Â·  4Comments