Mastering the art of chaining HTTP requests with RxJS for optimal results

I have a task that involves making multiple HTTP calls sequentially, examining the result of each call before proceeding to the next one. Depending on the response, I may need to display a message, continue to the next call, or break the chain. Additionally, I want to handle errors using a catchError block for each call. I've experimented with switchMap and iif, but I'm open to other suggestions.

Let's say I have create, update, and delete calls like the ones below. How can I capture the response of each call, evaluate it, and then trigger the next call?

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 access the response of each call sequentially and decide whether to 
        // continue or break based on the response
        
  });
});

Answer ā„–1

There may not be much more to add to this discussion.

It is worth noting that the EMPTY in RxJs is a stream that emits nothing and completes immediately. It can be likened to a "break" statement, though the manner in which you "break" from a stream can vary depending on the context.

this.service.create('/api/employee').pipe(
  catchError(err1 => {
    // perform some actions
    return throwError(err1);
  }),
  switchMap(resp1 => {
    // carry out some operations
    if(someCondition(resp1)){ 
      return this.service.update('/api/salary/', id).pipe(
        catchError(err2 => {
          // perform some actions
          return throwError(err2);
        }),
      );
    }
    return EMPTY;
  }),
  switchMap(resp2 => {
    // perform some actions
    if(someCondition(resp2)){ 
      return this.service.delete('/api/education/', id).pipe(
        catchError(err3 => {
          // perform some actions
          return throwError(err3);
        }),
      );
    }
    return EMPTY;
  }),
).subscribe({
  next: resp3 => { /*perform some actions*/ },
  complete: () => { /*Your stream has concluded*/ },
  eror: err => { /*All re-thrown errors are caught here */ }
});

Update

Utilizing tap to gain insight into streams

tap is an operator that mirrors the stream it receives without making any alterations. It can be used to observe the behavior of a stream at various points, aiding in comprehension.

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()

This example illustrates the actions taken before and after the switchMap operator. It is evident that in this scenario, switchMap receives a value from http1 and emits values from http2.

Due to the fact that switchMap waits for values from http1 before triggering http2, a consequence is that http2 only starts after http1 emits. This sequential execution is altered if http1 emits multiple times.

Further Reading:

Answer ā„–2

Implementing switchMap in this scenario is a recommended strategy:

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

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What are the best methods for testing REST API and Client-side MVC applications?

When dealing with a RESTful server that only responds with JSON data fetched from a database, and having a client-side application like Backbone, Ember or Angular, where should application testing take place? Is it necessary to have two sets of tests - on ...

Is it possible to center the image and resize it even when the window is resized?

My goal is to position an image in the center of the screen by performing some calculations. I've tried using: var wh = jQuery(window).innerHeight(); var ww = jQuery(window).innerWidth(); var fh = jQuery('.drop').innerHeight(); var fw = jQ ...

The specified timeout elapsed without the jasmine async callback being invoked

Having recently ventured into Protractor and javascript, I've encountered a persistent error that none of the existing solutions seem to shed light on. The issue revolves around understanding async callbacks within my Page Object model implementation. ...

Error 405: Angular encounters a method not supported while attempting to delete the entity

I have developed an application that performs CRUD operations on a list of entities. However, when attempting to delete an entity, the dialog box does not appear as expected. To start, I have a HttpService serving as the foundation for the CRUD operations ...

unable to choose just one material ui checkbox

I'm new to using React and I'm currently developing a simple todo app with React JS and Material UI. To accomplish this, I've created two separate components - one for taking user input (TodoInput) and another for rendering each individual t ...

Is it possible to implement pagination for API requests in a JavaScript and React environment?

I am currently working on an app that fetches data from a movie API and returns 20 items from page 1. I am now looking to implement pagination so that users can click a button to view more items from subsequent pages. Below is my current API call: export ...

What could be the reason for a jQuery script failing to execute when included in a PHP include statement from a different PHP page?

I'm currently working with javascript and php to manage cookies across different pages. On one page, I have a script that sets a value in a cookie variable and I want to retrieve that value on another page. Let's say the first page is named page1 ...

Assign a variable with the value returned by a function

Can you help me with this question I have about validating fields with a function using AbstractControl? errorVar: boolean = false function(c: AbstractControl): {[key: string]: string } | null { // validation if 'test' is true or not goes here ...

Oops! Property 'month' cannot be set on undefined value due to a TypeError

Despite not receiving any errors from Visual Studio Code, Iā€™m encountering an error in Chrome's console. Below is the code snippet from my interfaces.ts file: export interface Data1{ month: string; employeeName: string; date: string; employmentSta ...

Tips for tidying up duplicated typescript content sourced from a pre-existing library

Seeking guidance on implementing best practices and gaining a better understanding of my approach. After discovering the library react-google-calendar-api, I successfully installed it using npm in my React project. However, I wanted to expand its function ...

The JavaScript class failed to work properly within the asp.net framework

I have successfully implemented a JavaScript function on my aspx page. Here is the code snippet: <script type="text/javascript"> $(document).ready(function () { console.log("ready!"); var options = []; var ...

Issue with React Ref: Invariant Violation when trying to addComponentAsRefTo

I'm encountering an issue while attempting to add a ref to a React component. The error message I'm seeing is as follows: invariant.js:39Uncaught Invariant Violation: addComponentAsRefTo(...): Only a ReactOwner can have refs. You might be adding ...

Is there a way for me to retrieve the widths of all child elements within an HTML document?

I have been working on a JavaScript (jQuery) function to calculate the maximum width of all child and children's-child elements within a specific div element. Here is the code I have written so far: function setBodyMinWidth(name){ var max = 0; $(nam ...

How to retrieve values from HTML class names using Javascript for loops but encountering issues

foreach($products as $row){ <input type="hidden" class="prodId" name="id" value="<?php echo $row['id']; ?>"> <input type="hidden" class="prodUnique" name="unique" value="<?php echo $unique; ?>"> <button id="added" ...

Use JavaScript to overlay drawings onto an existing image

Within this particular image, I possess a compilation of pixel coordinates outlining the polygon segments that encompass all the objects contained within it (refer to the image provided below). For example, in relation to the individual, there exists a li ...

Submit button on Ajax form causes automatic page refresh

After adding a simple Ajax form to my WordPress website, I encountered an issue where the validation works fine, but instead of sending the email, the form refreshes after submitting. Here is the code snippet: <script type="text/javascript"> jQ ...

emulating the behavior of a synchronous XmlHttpRequest

While I have taken the time to explore similar questions like Pattern for wrapping an Asynchronous JavaScript function to make it synchronous & Make async event synchronous in JavaScript, I want to ensure that I consider all potential solutions. Is it ...

What is the best way to handle updating an npm package that is not the desired or correct version?

I've been experimenting with querying data on Firebase using querying lists. My attempt to implement functionality similar to the documentation resulted in this code snippet: getMatchesFiltered(matchId: string, filter: string, sortDirection: string, ...

Unable to See Success Notification on First Attempt

I am facing an issue with displaying a message when adding a new record. The first time I add a record, the message shows up correctly. However, if I try to add another record, the message does not appear even though the record is added successfully. Here ...

Obtain environment variables within a Strapi plugin

I am currently working on developing a Strapi local plugin, but I am facing an issue with retrieving variables defined in my .env file located at the root of my project. Specifically, I am trying to access this value within my React component (plugins/myPl ...