angularrxjsrxjs-subscriptions

how to subscribe in a conditional subscription result


I'm trying to perform 3 async actions (observables), one inside the other. 1. The first observable is the response of a modal dialog eventEmiter - the rest of the flow is depended on its response (let say that the modal return boolean emiter concerning to: "Do you want to delete the item"). 2. The second observable is the update (delete) action 3. The third is fetching back the new data after the deletion.

I'm using rxjs- and try to figure out how to do it without subscribe in a subscribe. See my code:

subscriptions : Subscription[] = [];

openDeleteDialog(data : any)
{
    const modalRef : NgbModalRef = this.modalService.open(ConfirmationDialogComponent); //Modal  dialoge reference
    this.subscriptions.push(modalRef.componentInstance.passResult.subscribe( 
    (result =>//This is the response from the modal dialog
      {
        if (result)
        {
          let updateApi : UpdateApi = new UpdateApi(data);
          this.srv.updateData(updateApi).pipe( //This is the update operation
            tap(() =>
            { 
              this.srv.getData(); //This is the fetch data operation
            }
            )

          ).subscribe();
        }
      }
    )
    ));
} 

Solution

  • You can use pipe, filter and switchMap for that:

    subscriptions : Subscription[] = [];
    
    openDeleteDialog(data : any)
    {
      const modalRef : NgbModalRef = this.modalService.open(ConfirmationDialogComponent); //Modal  dialoge reference
      this.subscriptions.push(
        modalRef.componentInstance.passResult
         .pipe(
           filter((result) => !!result),
           switchMap((result) => {
              let updateApi : UpdateApi = new UpdateApi(data);
              return this.srv.updateData(updateApi);
           }),
           switchMap((updateResult) => this.srv.getData())
         ).subscribe((getDataResult) => console.log(getDataResult))
      );
    }
    

    First you use filter to only pass the data when result is something, then you switch to a new observable, the update data observable, and at the same time you pipe that one to switch to the get data observable. That way you chain the observables, I am guessing you need to wait for the update data result to get the data again.

    EDIT: Additional piece of information, you were using tap to call this.srv.getData(), but if that returns an observable with the http request, that request is never going to be called, since you need to subscribe to it in order for the request to be made. As a general rule I use the tap pipe for collateral effects that will only need the result of the observable but will not modify anything else that is observable related, if that makes any sense.