Sınav Alemi
Sınav Alemi

Reputation: 53

Angular Multiple Observable Requests with using Service

Demo In my application I am using service to communicate between

import {Injectable} from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { TransferModel } from '../models/transfer';

@Injectable()
export class TransferService{
    constructor(){}
    private paramSource = new BehaviorSubject(new TransferModel());
    getData = this.paramSource.asObservable();
    setData(param:TransferModel) { this.paramSource.next(param)} 
}

My problem is that when I go to components, it works well but in pages send other pages request also. I mean for example I am in Courses.component

 constructor(private transferService:TransferService,private dataService:DataService,sessionService:SessionService,private router:Router) { 
    this.transferService.getData.subscribe(x=>{
      this.transfer=x; if(!this.transfer.ExamId || this.transfer.ExamId<=0){ this.router.navigateByUrl("/home");return;}
      this.dataService.Post(URLS.url.coursePage.getCourses,{Id:this.transfer.ExamId}).subscribe(elem=>{
        this.courses=elem;
      });
    });  
 }

code above gets courses list when I click one course , below function run and

 goToSubject(id){
    this.transfer.CourseId=id;
    this.transferService.setData(this.transfer);
    this.router.navigateByUrl("/subjects");
  }

goes to subjects component. In subjects component I send request with constructor.

 constructor(private transferService:TransferService,private dataService:DataService,sessionService:SessionService,private router:Router) { 
     this.transferService.getData.subscribe(x=>{
       this.transfer=x; if(!this.transfer.ExamId || this.transfer.ExamId<=0){ this.router.navigateByUrl("/home"); }
       this.dataService.Post(URLS.url.subjectPage.getSubjects,{ExamId:this.transfer.ExamId,CourseId:this.transfer.CourseId}).subscribe(elem=>{
         this.subjects=elem;
       });
     });  
   } 

but here also another page's request call too such as in image. I need that every page send only one its request.

How can I solve this problem?

Thanks in advance enter image description here

Upvotes: 2

Views: 654

Answers (1)

j4rey
j4rey

Reputation: 2677

I assume since transferService.getData() returns a Subject, which you are subscribing, and probably not unsubscribing on component onDestroy anywhere, those subscription remains alive and are invoked.

Your goToSubject() calls the this.transferService.setData(this.transfer); which basically invokes all the subscriptions.

You would need to hold on the Subscription being returned when you subscribe and call unsubscribe() on ngOnDestroy()

subscription: Subscription;
constructor(...){
    this.subscription = this.transferService.getData.subscribe(x=>{
        ...
    });
}

ngOnDestroy() {
    if(this.subscription) {
        this.subscription.unsubscribe();
        this.subscription = null;
    }
}

if you have multiple subscribe() on your component, maybe you would like to leverage some sort of self-subscribing-implementation like takeUntil

Note: Angular HttpClient subscriptions are self-unsubscribing by default, so you don't need to call unsubscribe() when you call httpClient.get().subscribe(). For everything else, you would need to call unsubscribe().

UPDATE:

After looking at the stackblitz demo you've provided, it was confirmed that the issue was with the transferService.getData() subject. However even with the ngOnDestroy() unsubscribing it was still calling because you had this.transferService.setData(..) before you redirected which basically invokes the transferService.getData().subscribe(...).

To fix that without major refactoring you would have to make it 'Subscribe only once' or 'automatically unsubscribe as soon as it subscribe is called'. Which brings us back to takeUntil.

in both courses.component & subjects.component

constructor() {
    const subj: Subject<boolean> = new Subject<boolean>();
    this.transferService.getData
        .pipe(takeUntil(subj))
        .subscribe((result) => {
            subj.next(true);
        });
 }

UPDATE 2:

Stackblitz demo link

Upvotes: 2

Related Questions