0

I have a button, clicking it will make a service call. Finally I want to inform the user by email. The email will be made by another service call.

public submitForm = (data, selected = {} ) => {
    console.log(data);
    this.service['submit'].post({body: data}).subscribe(
    () => { null },
    error => {
       console.log(error);
    };
    () => {
         // second subscribe
        this.service['email']['post']({ body: theForm.value }).subscribe(
        () = > {
           // data processing
         }
       );
     }
     );}

You see it is the nested subscribe. I use angular 5 and rxjs 5.5. How to avoid it?

UPDATE:

By the comment, I added the service code

public readonly service: SwaggerService

The actually all services are in asp.net web api, for example

[HttpPost]
[Route("email")]
public ActionResult postEmail([FromBody]EmailBody email)
{}
Bigeyes
  • 1,508
  • 2
  • 23
  • 42

2 Answers2

0

You can use switchMap to avoid nested subscription like this:

public submitForm = (data, selected = {} ) => {
  console.log(data);
  this.service['submit'].post({body: data})
      .switchMap(() => {
        return this.service['email']['post']({ body: theForm.value })
                  .catch(err => {
                    //handle your error here

                    //HERE YOU NEED TO DO YOUR SELF; MAKE SURE TO RETURN AN OBSERVABLE FOR HERE.
                    //I ON RXJS 6.4; So I am not sure what is `of` operator in rxjs 5.5
                    //I guss it is Observable.of
                    return Observable.of(err);
                  });
      })
      .catch(err => {
        //handle your error here

        //HERE YOU NEED TO DO YOUR SELF; MAKE SURE TO RETURN AN OBSERVABLE FOR HERE.
        //I ON RXJS 6.4; So I am not sure what is `of` operator in rxjs 5.5
        //I guss it is Observable.of
        return Observable.of(err);
      })
      .subscribe((resultOfSecondCall) => {
        //do your processing here...
        console.log(resultOfSecondCall);
      });

   }
user2216584
  • 5,387
  • 3
  • 22
  • 29
0

That's not the way I would do it. You haven't posted any of the your service code, so it's hard to tell you exactly how to do it. I will make an assumption that your service code is doing nothing but making an http call to the server (and therefore returning a promise/something awaitable)

await this.service['submit'].post({body: data});
await this.service['email']['post']({ body: theForm.value });

Using rxjs over standard HttpClient/Promises doesn't seem to hold any benefit here. The only real requirements seems to be that you need the first call to execute (successfully) before you fire off the email. I would just do two lines of code using await rather than chaining some observables here.

As a side note, in order to await an HttpClient call, you have to convert it to a promise first. IE: this.httpClient.post(url, data).toPromise();

mwilson
  • 12,295
  • 7
  • 55
  • 95
  • I updated the service, let me know if any question. – Bigeyes Jul 16 '19 at 23:46
  • That isn't the service code. It's not clear that your `service` is of the `SwaggerService` type but we have no idea what your method in said service is doing. – mwilson Jul 16 '19 at 23:49
  • The service code is too long. Sorry about it. And is it necessary to need service code? Because I saw a lot of similar questions without service still got answered. – Bigeyes Jul 16 '19 at 23:57