Home > Blockchain >  Using RxJS in Angular with conditional / combined subscriptions
Using RxJS in Angular with conditional / combined subscriptions

Time:01-06

in my Angular App I have an API service like so that contains two methods:

addComment(id: string, comment: string): Observable<any> {
    return this.http.post(`api/${encodeURIComponent(id)}/comment`, { comment }).pipe(
      map(this.apiUtils.extractData)
    );
  }


closeAccount(id: string): Observable<any> {
    return this.http.post(`api/${encodeURIComponent(id)}/closeaccount`, {}).pipe(
      map(this.apiUtils.extractData)
    );
}

Now in my app I have a component where I can close a user account and if a comment is added I wish to add a comment before closing the account, but this is conditional, sometimes a user doesn't need to add a comment before closing an account. In my component file I have created a method for this but I am a bit stuck with something... here is my component code where I collect my user data and comment from a form. If we have a comment we call the api to add the comment and when that resolves I call the API to close the account. If no comment has been submitted I just call the api to close the account. This is okay, but hardly eloquent! Please note I have reduced the code to improve readability.

constructor(private formBuilder: FormBuilder,
            public apiService: ApiService) {}

// i have omitted the code where I create my form and validation

closeAccount(): void {
    // get values from my form
    const id = this.closeAccountForm.controls.id.value;
    const comment = this.closeAccountForm.controls.closeAccountComment.value; 

    if (comment) {
        this.apiService.addComment(id, comment).subscribe(() => {
            this.apiService.closeAccount(id).subscribe(() => {
                // now do something
            });
        })
    } else {  
        this.apiService.closeAccount(id).subscribe(() => {
            // now do something
        });
    }
}

I was wondering if I can reduce the code and prevent the duplication of calling the closeAccount method. Does RxJS provide a way for me to apply the conditional logic in a method? What I have above works but is pretty ugly!

I'm currently reading the docs but sometimes people can provide an answer quicker. If I find an answer/solution I shall provide it here. Many thanks in advance. If my wording is bad please say so and I shall rework my question.

CodePudding user response:

try this:

const preCloseAction = comment ? this.apiService.addComment(...) : of(null);

preCloseAction.pipe(
  switchMap(() => this.apiService.closeAccount(id))
).subscribe(() => {
  // now do something
})

or, if the result of comment doesnt matter during closeAccount call

concat(
  !comment ? EMPTY : this.apiService.addComment(...),
  this.apiService.closeAccount(id)
).pipe(last()).subscribe(() => {
  // now do something
})

CodePudding user response:

If order of the requests doesn't matter you could just remove the call from inside the if clause and remove the else.

closeAccount(): void {
    ... 

    if (comment) {
        this.apiService.addComment(id, comment).subscribe(); 
    } 

    this.apiService.closeAccount(id).subscribe(() => {
       // now do something
    });
}

If the order matters, you could setup the observable for the request based on the condition, and then call subscribe on the resulting one.

 closeAccount(): void {
    ...
    const request = comment 
      ?  this.apiService.addComment(id, comment).pipe(
           switchMap(_ => this.apiService.closeAccount(id))
         ) 
      : this.apiService.closeAccount(id);

    request.subscribe(() => {
       // now do something
    });
}

Cheers

  •  Tags:  
  • Related