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();
});