Reputation: 5167
I have an Angular service which keeps an private BehaviorSubject
so that it can read the value at any given time. It is private so that any component that uses it cannot manipulate it. Instead, a regular Observable
is exposed as public. The BehaviorSubject
is now a consumer of any data emitted by this observable.
public subheaderData$: Observable<SubheaderData>;
private subheaderDataSubject$: BehaviorSubject<SubheaderData> = new BehaviorSubject<SubheaderData>(null);
constructor(private repository: SubHeaderRepository) {
this.subheaderData$ = this.load();
this.subheaderData$.subscribe(this.subheaderDataSubject$);
}
As you can see, I am calling .subscribe
from my service, which makes my observable hot immediately. What I would like to accomplish is that a component which injects this service must subscribe to the public Observable
, and when that happens, the BehaviorSubject
should automatically be added as an observer, even though the component has no knowledge of it (due to it being private.
How can this be accomplished?
Upvotes: 0
Views: 308
Reputation: 96969
If I'm not missing anything critical I think you should be able to accomplish what you want only by using multicast
even though this will be a little unusual use-case.
subheaderDataPublic$ = this.subheaderData$.pipe(
multicast(this.subheaderDataSubject$, s => s),
);
Then in your component you'll subscribe to subheaderDataPublic$
.
Typically, you'd use multicast
for example like this:
multicast(new Subject(), s => merge(s, s.pipe(...)))
... but if you pass it this.subheaderDataSubject$
it'll be used as an intermediate Subject. That s => s
above is required because without any selector function multicast
returns an instance of ConnectableObservable
which is probably something you don't need.
EDIT: Maybe a better understandable solution would be using just Observable
constructor.
subheaderDataPublic$ = new Observable(observer => {
const subscriptions = new Subscription();
subscriptions.add(this.subheaderData$.subscribe(this.subheaderDataSubject$));
subscriptions.add(this.subheaderDataSubject$.subscribe(observer));
return () => subscriptions.unsubscribe();
});
Upvotes: 1
Reputation: 19933
Do this in your service constructor
this.subheaderData$ = this.subheaderDataSubject$.asObservable();
then subscribe to subheaderData$
whenever needed
and you can this.subheaderDataSubject$.next(someValue)
in your service
Upvotes: 1