Home > Net >  Angular - Subscribe response repeated multiple times on each call
Angular - Subscribe response repeated multiple times on each call

Time:11-09

Objective: I'm working with a service. The objective is to create a service that will serve as a creation for confirmation dialog and will return whether confirm or cancel was clicked in the popup.

Code:

product.component.html

<button  (click)="confirmFeatureProductDialog(data)">Confirm</button>

product.component.ts

  confirmFeatureProductDialog(product){
    let message = "Do you want to set this product?";
    let result;
    this._popupDialogService.confirmationPopup(message).subscribe(
      (res)=>{
        console.log("Running")
        result = res;
        if(result){
          this.featureProduct(product._id);
        }
      }
    );
  }

popupDialog.service.ts

import { Injectable } from "@angular/core";
import { Observable, Subject } from "rxjs";
import Swal from 'sweetalert2'

Injectable();
export class PopupDialogService {

    public mySubject = new Subject<boolean>();

    confirmationPopup(textDetail?): Observable<any> {
        Swal.fire({
            title: 'Are you sure?',
            text: textDetail,
            icon: 'success',
            showConfirmButton: true,
            showCancelButton: true,
        }).then((result) => {
            if (result.value) {
                this.mySubject.next(true);
                return;
            }
            Swal.close();
        });
        return this.mySubject.asObservable();
    }
}

Result & Issue:

When I run this the first time everything seems to be working fine.

When I click on the button the 2nd time after clicking either cancel or confirm the response from the product.component.ts is duplicated twice i.e the console.log from the subscribe response is repeated twice and console.log shows "Running" "Running".

When I click the button third time (once the dialog closes after clicking confirm/cancel) the response is repeated thrice and console shows "Running" 3 times.

Things I've tried so far:

Add the service to app.module.ts provider instead of product.module.ts providers. Doesn't change anything.

Checked if the service's constructor is called multiple times on 2nd and onwards execution. It doesn't execute multiple times. Only the subscription response is executed multiple times.

Summary:

Running subscription on a function returning observable from service. First time the response of the subscription is okay however when the function is re-opened the 2nd time it throws the response twice, after closing and re-running the function gives the response thrice and so on.

CodePudding user response:

this issue is occurs because of observer of this._popupDialogService.confirmationPopup(message)

you need to declare in product component for subscription:

subscription!: Subscription

confirmFeatureProductDialog(product){
    let message = "Do you want to set this product?";
    let result;
    this.subscription =this._popupDialogService.confirmationPopup(message).subscribe(
      (res)=>{
        console.log("Running")
        result = res;
        if(result){
          this.featureProduct(product._id);
        }
      }
    );
  }

in ondestory lif cycle hook just unsubscribe it.

ngOnDestroy() {
        this.subscription.unsubscribe()
    }

CodePudding user response:

try to change your method like:

sub: Subscription;
confirmFeatureProductDialog(product){
    let message = "Do you want to set this product?";
    let result; 
    this.sub = this._popupDialogService.confirmationPopup(message).subscribe(
      (res)=>{
        console.log("Running")
        result = res;
        if(result){
          this.featureProduct(product._id);
        }
        this.subs.unsubscribe();
      }
    );
}

That it could fix your issue, but I think in your case you need a different approach to the problem. Maybe it's better using a service like that:

export class DialogService {

  dialogConfig: EventEmitter<DialogConfig> = new EventEmitter(null);
  afterClosed: EventEmitter<DialogResponse> = new EventEmitter(null);

  constructor() { }

  /** OPEN DIALOG DEFINED IN APP.COMPONENT.HTML
   * 
   * @title define the optional title of a dialog (title to translate with pipe translate)
   * @action action define the action component to use
   * @message define the message of a dialog (message to translate with pipe translate)
   * 
  */
  open(title: string, action: string, message?: string, params?: Object): EventEmitter<DialogResponse> {
    this.afterClosed = new EventEmitter(null);
    this.dialogConfig.emit({
      visibile: true,
      title,
      action,
      message,
      params
    });
    return this.afterClosed;
  }

  /** CLOSE DIALOG DEFINED IN APP.COMPONENT.HTML */
  close(res: boolean, note?: string) {
    this.dialogConfig.emit({ visibile: false });
    note ? this.afterClosed.emit({ response: res, note: note }) : this.afterClosed.emit({ response: res });
  }

}

used in your components like this for open:

this.dialog.open("title", "action", "message").subscribe(res => {
   ...stuffs
})

and for close:

this.dialog.close(true | false)
  • Related