I'm new to rxjs/observables. They're a bit over my head so this may be a simple question.
I want to have a subject in a service which can be frequently triggered to get updates. The update could then be immediately returned to the caller (if they wait), but also emitted to any subscribers. I'd like the subject to be private so only the service can .next()
it.
The last caveat is, when something subscribes to the observable I'd like to get the current value ONCE, and then be alerted to any updates after that. My rookie attempt is below. It seems to mostly work, but the page subscription gets the current value once per call of next()
on initial subscribe. So if getNewThings()
was called 5 times, the page subscription would immediately get the current subject value 5 times. How can I fix that?
Service
@Injectable()
export class PretendService{
private mySubject: BehaviorSubject<Thing[]> = new BehaviorSubject<Thing[]>(null);
public readonly mySubjectObservable: Observable<Thing[]> = this.mySubject.asObservable();
...
public getNewThings(): Promise<Thing[]>{
let p = new Promise<Thing[]>((resolve, reject) => {
//Do the work to get Thing[]s
let theThings: Thing[] = [];
mySubject.next(theThings);
resolve(theThings);
}
return p;
}
}
Page
...
thingSubscription: Subscription;
constructor(private pretendService: PretendService){
this.thingSubscription = this.pretendService.mySubjectObservable.subscribe((things)=>{
//ISSUE HERE:
//This fires once per .next() with the current value on initial subscription
console.log(`got some things [{things}]`);
});
}
...
//Unsubscribe in destructor...etc...
UPDATE
Here is a stackblitz that shows some of this. Clicking the main button will trigger the refresh method multiple times. Then click the "Other Page" link to trigger the subscription. Notice on the Page2 component there is an OnDestroy
implementation that can be commented/uncommented. That was my main issue - I wasn't destroying properly, so it was gathering subscriptions.
https://stackblitz.com/edit/angular-umk8qm?embed=1&file=src/app/page2.component.ts
See the StackBlitz on the update. In my case I was not implementing OnDestroy
properly, which caused my app to accumulate subscriptions. This looked like it was getting 1 update per next()
call on the BehaviorSubject
. However, it was just getting 1, but since there were lots of subscriptions building up it appeared like 1 subscription was getting multiple updates. A more complete implementation is below.
Page
export class Page2Component implements OnDestroy
...
thingSubscription: Subscription;
constructor(private pretendService: PretendService){
this.thingSubscription = this.pretendService.mySubjectObservable.subscribe((things)=>{
console.log(`got some things [{things}]`);
});
}
...
ngOnDestroy() {
//This should fire if things are destroying properly
console.log('destroying!');
this.thingSubscription && this.thingSubscription.unsubscribe();
}
....