1

I want to make several HTTP calls sequentially and after each call, I want to examine the result and make another call and display message, etc. In some cases continue to the next call, some cases break on that call after displaying message. On the other hand, I also need to use catchError block of each call (or maybe a single block for all of them, but using one for each call would be better).

So, assume that I have an create, update and delete calls as shown below. How can I get each of these call's response and check the response and then execute another call?

I have tried switchMap and iif and I am looking a solution using one of them. Any suggestion?

this.service.create('/api/employee').subscribe(resp1 => { this.service.update('/api/salary/', id).subscribe(resp2 => { this.service.delete('/api/education/', id).subscribe(resp3 => { // I need to get response of each call from starting thr first and then continue of // break according to the condition of the response }); }); 

2 Answers 2

2

I'm not sure there's much else to say here.

Of note, perhaps, is that EMPTY is an RxJs stream that emits nothing and completes immediately. It is sort of like "break" (in a pretty loose way. How you "break" from a stream can be pretty context dependant).

this.service.create('/api/employee').pipe( catchError(err1 => { // do some stuff return throwError(err1); }), switchMap(resp1 => { // do some stuffs if(someCondition(resp1)){ return this.service.update('/api/salary/', id).pipe( catchError(err2 => { // do some stuff return throwError(err2); }), ); } return EMPTY; }), switchMap(resp2 => { // do some stuff if(someCondition(resp2)){ return this.service.delete('/api/education/', id).pipe( catchError(err3 => { // do some stuff return throwError(err3); }), ); } return EMPTY; }), ).subscribe({ next: resp3 => { /*do some stuff*/ }, complete: () => { /*Your stream is done*/ }, eror: err => { /*All re-thrown errors end up here */ } }); 

Update

Using tap to help understand streams

tap is an operator that returns the same stream that it receives. It can't make any changes to your stream, but it can look at what is happening at any given point. This can be a useful tool to aid your understanding.

http1().pipe( tap({ next: val => console.log("Result from http1 call: ", val), complete: () => console.log("http1 call completed"), error: err => console.log("http1 call errored: ", err) }) switchMap(val => http2(val).pipe( tap({ next: val => console.log("Result from http2 call: ", val), complete: () => console.log("http2 completed"), error: err => console.log("http2 call errored: ", err) }) )), tap({ next: val => console.log("Result from switchMap operator: ", val), complete: () => console.log("switchMap completed"), error: err => console.log("switchMap (http1 or http2 call) errored: ", err) }) ).subscribe() 

Here we can see what is happening before and after the switchMap. You can see that in this case, switchMap is taking a value from http1 and emitting the values from http2.

Because switchMap waits for values from http1 before generating http2, one side effect is that http2 doesn't start until after http1 emits. This does mean that these calls are executed sequentially, but the story gets more complicated if http1 emits more than once.

More About:

Sign up to request clarification or add additional context in comments.

5 Comments

Voted up, but anyhow, I cannot make it work. But I think I made a mistake.
I have some question, related to this approach: 1 I think return EMPTY or return NEVER ara used to finalize the stream at any point. Is that true? 2. What if we want to make the stream continue in the switchMap block? 3. As far as I understood, the idea behing switchMap is to execute HTTP calls sequentially and make some operation and error handling in its block. Is that true?
Both NEVER and EMPTY never emit any values. NEVER is a stream that 'lives' forever. It never completes and must be unsubscribed. EMPTY completes immediately. switchMap takes a stream of values and uses those to compute and subscribe to a stream. The stream it subscribes to is the one computed from the most recent value (Everything else is dropped). With mergeMap you never drop old streams, just merge them into the new one.
switchMap is often used for HTTP calls since you expect only one response and switchMap is simpler/smaller than mergeMap.
You rock! The last update is really very clean and easy to understand. For diagnostic, it is really very helpful. But, for using at last step, should I still use this approach and make necessary controls by checking the value in the complete section by using the next value? If so, can I create a block and execute another http call in that?
1

Using switchMap here is a good approach:

this.service.create('/api/employee') .pipe(switchMap((resp) => { if(fulfillsCondition(resp)) { return this.service.update(...); } return this.service.delete(...); })).subscribe(); 

4 Comments

Thanks for reply, it seems to be good and I wil try asap. But what about the catchError blocks? I also need to use them to catch error and add an if block in that catchError blocks. Could you pls add also that blocks by adding an empty if (because generally I encounter void error and it would be better to see correct usage with teh help of you :)
Would you mind an update regardimng to my last comment? regards.
It seems to work, but I need to iömplement catchError((err: any) => {...} on the correct places for each call (it may also be ok using a single catch block for each call. Could you update your code please to perform this? Thanks in advance.
I have some question, related to this approach: 1 I think return EMPTY or return NEVER ara used to finalize the stream at any point. Is that true? 2. What if we want to make the stream continue in the switchMap block? 3. As far as I understood, the idea behing switchMap is to execute HTTP calls sequentially and make some operation and error handling in its block. Is that true?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.