Reputation: 2240
I have a service that has a method that returns and observable. I have a component that subscribes to that observable when my it is loaded. I have a console.log in my service to log every time it is called. When I run my app and look at my console window, I see 3 instances of my logged value. Why is that? I'm only subscribing to the observable service once.
I actually have a broader question than this simple example where I noticed that when I have several subscriptions to my service, I get even more repeated calls to my functions and the service. Why does that happen given that my assumption is that the purpose of using rxjs and subjects is to have some basic form of state management and the purpose of that being to avoid retrieving data that hasn't changed.
Service:
export class ResultService {
protected id;
private results$ = new Subject<any>();
constructor(
private dataService: DataService,
) { }
getResults(id): Observable<any> {
console.log('get result called in ResultService');
this.dataService.getResults(id)
.subscribe(res => {
console.log('the value of res in ResultService constructor');
this.results$.next(res);
})
return this.results$.asObservable();
}
}
Result Component
private subscription$;
@Input() id;
constructor(
this.subscription$ = this.resultService.getResults(this.competitionId);
this.fetchResults(this.competitionId);
) { }
ngOnInit() {
this.fetchResults(this.id);
}
fetchResults(id){
this.resultService.getResults(this.id)
.subscribe((data) =>
{
data.forEach(resultElement => {
//do something
});
this.resultList = data;
})
}
ngOnChanges() {
this.fetchResults(this.id);
}
ngOnDestroy() {
this.subscription$.unsubscribe(); //unsubscribe
}
Summary Page html file - has the result component as a child that it passes id
<ion-col size-lg="5">
<ion-row>
<ion-col>
<app-results-component [id]="id"></app-results-component>
</ion-col>
</ion-row>
</ion-col>
Summary Page ts file
private id: number;
private dataSub$;
private resultData : any;
ngOnInit() {
this.activatedRoute.params.subscribe(params => {
this.competitionId = params['id'];
this.getData(this.id);
}
}
getData(id) {
this.dataSub$ = this.resultService.getResults(id);
this.dataSub$
.subscribe((data) => {
this.resultData = data;
this.dosomething(this.resultData);
})
}
ngOnDestroy() {
this.dataSub$.unsubscribe(); //unsubscribe
}
Upvotes: 2
Views: 5036
Reputation: 8633
You need to add if condition if (changes.id)
It seems there's no need to call it in onInit
You need to unSubscribe the observable
private unSub = new Subject();
constructor(
private resultService: ResultService
) { }
fetchResults(id){
this.resultService.getResults(this.id)
.pipe(
takeUntil(this.unSub)
)
.subscribe((data) =>
{
data.forEach(resultElement => {
//do something
});
this.resultList = data;
})
}
ngOnChanges(changes: SimpleChanges) {
if (changes.id) {
this.fetchResults(this.id);
}
}
ngOnDestroy(): void {
this.unSub.next();
this.unSub.complete();
}
Upvotes: 0
Reputation: 4692
You have to unsubscribe your subscription.
Sample code:
constructor(
private resultService: ResultService
) { }
subscription$ //declare
ngOnInit() {
this.fetchResults(this.id);
}
fetchResults(id){
this.subscription$ = this.resultService.getResults(this.id)
.subscribe((data) =>
{
data.forEach(resultElement => {
//do something
});
this.resultList = data;
})
}
ngOnChanges() {
this.fetchResults(this.id);
}
ngOnDestroy() {
this.subscription$.unsubscribe() //unsubscribe
}
}
Upvotes: 1