Home > Software design >  How to execute subscribe method inside subscribe?
How to execute subscribe method inside subscribe?

Time:10-26

I'm trying to implement somethink like that (I will show pseudo-code because real implementation is too big for paste it here)

FunctionOne(){
  const dialogRef = this.dialog.open(ShowSomethinComponent)

  const subForDialog = dialogRef.componentInstance.someAction$
      .subscribe((response) => {
        this.openReportIssueModal(response, dialogRef) 
      });
  
}


openReportIssueModal(dialogRef: MatDialogRef<ShowSomethinComponent, any>){
    this.reportIssueModalService.onModalClosed.subscribe((data) => {
      dialogRef.componentInstance.DoSomething();
})

// explanation from service
onModalClosed from service is:  onModalClosed = new Subject<boolean>();
// ****simply triggered from HTML****
private reportMeasurementSubject = new Subject<InspectionMeasurement>();
  reportMeasurementAction$ = this.reportMeasurementSubject.asObservable();

openReportIssueModal(meassurement: InspectionItem) {
    this.reportMeasurementSubject.next(meassurement)
  }

// ****from service****
this.reportIssueDialogRef.afterClosed().subscribe((issueSavedSuccessfully: boolean) => {
  this.onModalClosed.next(issueSavedSuccessfully);
            })

problem is that first time onModalClosed emit, all is okey
but after it emits second time , it trigger subscribe function from openReportIssueModal two times,
when it emit third time , it trigger it three times etc.

Why it works like that?

recreated problem, please click start flow > click emit > back > click emit> back ....... and see console result

https://stackblitz.com/edit/mat-dialog-example-ndobeg?file=app/app.component.ts

CodePudding user response:

Well, you are subscribing to onModalClosed each time openReportIssueModal is called. The subscription is never unsubscribed, so multiple subscriptions will be instantiated. Since you also have a Subject which never completes, you basically created a memory leak.

Good news: You can easily prevent this behavior if you use rxjs take operator, to only take the first value emitted by onModalClosed and afterwards complete (basically unsubscribe):

this.reportIssueModalService.onModalClosed.pipe(take(1)).subscribe((data) => {
      dialogRef.componentInstance.DoSomething();

This logic probably also applies to your someAction$ variable, but since I am not sure how it was instantiated, I cannot tell you for sure.

Note: A more declarative pattern would be the following. You would switch to a new observable which will then be subscribed to. New emissions will be omitted until the first value from onModalClosed is emitted.

const subForDialog = dialogRef.componentInstance.someAction$.pipe(
  exhaustMap(() => this.reportIssueModalService.onModalClosed.pipe(
    take(1)
  ))
)
.subscribe((response) => {
  dialogRef.componentInstance.DoSomething();
});
  • Related