Nested RxJS subscribe with error handling actions

I have a block of code that contains nested subscribe calls:

this.http.post('/update1', newData).subscribe(
    (response) => {
        const r = response.json;
        const id = r['id'];
        this.http.post('/update2?id=' + id, newData).subscribe(
            () => {
                this.http.post('/update3?id=' + id, newData).subscribe(
                    () => {
                        console.log('success');
                    },
                    () => {
                        // revert changes made to update2
                        this.http.post('/update2', previousValues).subscribe();
                        // revert changes made to update1
                        this.http.post('/update1', previousValues).subscribe();
                    });
            },
            () => {
                // revert changes made to update1
                this.http.post('/update1', previousValues).subscribe();
            }
        );
    },
    (error) => {
        console.log(error);
    }
);

Looking for guidance on optimizing this code using RxJS 5?

Answer №1

Avoid nesting subscribe calls within each other. By utilizing standard RxJS operators, there is a more efficient approach:

this.http
  .post('/update1', newData)
  .pipe(
    map((response) => response.json),
    map((data) => data.id),
    switchMap((id) =>
      this.http.post('/update2?id=' + id, newData).pipe(
        switchMap(() => this.http.post('/update3?id=' + id, newData)),
        catchError((err) => {
          // Handle errors from update3
          return merge(
            // Undo changes made in update2
            this.http.post('/update2', previousValues),
            // Undo changes made in update1
            this.http.post('/update1', previousValues),
          );
        }),
      ),
    ),
    catchError((err) => {
      // Handle errors from update2
      // Undo changes made in update1
      return this.http.post('/update1', previousValues);
    }),
  )
  .subscribe(
    (result) => {
      console.log(result);
    },
    (err) => {
      // Handle uncaught errors
      console.log(err);
    },
  );

This way, you only need one subscribe method to manage the final result if desired.

Remember that catchError() within the pipe will be triggered by any exceptions thrown before it. If an exception has already been handled, it won't trigger additional catchError() calls.

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

Incorrect conditions when attempting to compare text strings

My current code retrieves the user's locale and saves it in a variable. I have implemented a conditional statement that checks if the locale matches a specific value - as shown in the image below: https://i.sstatic.net/ASVZ8.png In the screenshot, y ...

How can I handle custom validation in Angular 6 template-driven forms if there is "no provider" available?

I am currently following the instructions outlined in the documentation found at https://angular.io/guide/form-validation#custom-validators After using the ng generate command, I have successfully added a new directive to my project. import { Directive} ...

Angular - Using the 'name' attribute with the 'mat-select' element

Currently, I am working on an Angular form that involves the dynamic nature of the userEntitiesRoles array. To ensure smooth functionality, each mat-select tag within the ngFor loop requires a unique name attribute. In order to achieve this, I attempted to ...

Ways to assign a default value to a radio button using a mock JSON dataset

As a beginner in AngularJS2, I am looking to resolve an issue where the checkbox is automatically checked when retrieving values from a mock JSON file. Can someone please help me? <div class="form-row"> <div class="formHeading">Skills *< ...

Migrating the Angular application from version 4.x.x to 6.0

I am currently working on a large open source project built on Angular 4. The project has many components and I am facing challenges in updating it to Angular 6. Even though the official site https://update.angular.io/ provides guidance, manually searchi ...

Tips for avoiding storage issues in Angular Server-Side Rendered application using guards and services (Angular V17)

Is there a way to prevent undefined localStorage/Sessionstorage errors in Angular V17 SSR apps without using the old platformId? I am looking for an equivalent of afterNextRender that can be used in services or guards, whether they are functional guards or ...

struggling with typing an object in react typescript - Element is assumed to have an 'any' type due to its type

Having trouble with the code snippet below: // if I remove the `any` below it breaks. const teams: any = { liverpool: <Liverpool />, manUtd: <ManUtd />, arsenal: <Arsenal />, }; export const TeamCrest = ({ team }: { team: ke ...

Can dynamic values be sent to a custom form validator in Angular 6?

Essentially, I am facing a challenge with validating form inputs that are interdependent (for example, ensuring that the "from" time is earlier than the "to" time). However, I'm unsure of the best approach to tackle this issue. Below is my form group ...

Customize the size of data points on your Angular 2 chart with variable

In my Angular 2 application, I am utilizing ng2-charts to create a line chart. The chart functions properly, showing a change in color when hovering over a point with the mouse. However, I want to replicate this behavior manually through code. Upon clicki ...

Assigning string properties to different types

I have numerous data types, each with a common property called dataType, and I am currently mapping each one to that specific value: interface GroupData { dataType: "group"; name: string; people: PersonData[]; } interface PersonData ...

Tips on transferring information to the graphical user interface

Here is my code snippet: signup.post('/signup', urlendcodedParser, async(req: Request, res: Response) => { const username = req.body.username; const password = req.body.password; const age = req.body.age; const email = req ...

Using Checkbox from material-UI to add and remove strikethrough on a to-do list task

const Todo: React.FC<ITodoProps> = (props) => { const [textInput, setTextInput] = useState(''); const { addTodo, userId, todosForUser, user, } = props; if (user == null) { return ( <Grid container={true} direction=&apo ...

Alternatives to using wildcards in TypeScript

In my code, I have defined an interface called ColumnDef which consists of two methods: getValue that returns type C and getComponent which takes an input argument of type C. Everything is functioning properly as intended. interface ColumnDef<R, C> { ...

An issue occurred: The function Observable_1.Observable.from is undefined

I encountered an issue when using @select() and async pipe. The problem arose while downloading a course here, specifically at lesson 6. Everything was functioning properly before this point. https://i.sstatic.net/bLAK4.jpg ................................ ...

Utilize React's useRef with ChakraUI Toasts

Struggling to figure out what specific type I need to provide for React.useRef() when looking at the code snippet provided in the Chakra docs: function UpdatingToastExample() { const toast = useToast() const toastIdRef = React.useRef() function upda ...

The expanded interfaces of Typescript's indexable types (TS2322)

Currently, I am in the process of learning typescript by reimagining a flowtype prototype that I previously worked on. However, I have hit a roadblock with a particular issue. error TS2322: Type '(state: State, action: NumberAppendAction) => State ...

Improve the Precision of Return Types in Typescript by Specifying Targeted Signatures for Functions with Generic Parameters

I have the following types: interface AutosuggestState<Item> { highlightedIndex: number | null; inputValue: string | null; isOpen: boolean; selectedItem: Item | null; } interface ItemToString<Item> { (item: Item): string; } interfa ...

Shortcut for importing Angular 2

As I work on developing an application using Angular 2 and Webpack, I find myself needing to import components from directories higher up in the hierarchy. Currently, my imports look something like this: import { UserComponent } from '../../../models ...

The transition from Angular 14 to Angular 15 leads to a compatibility issue with constructor parameters in a library

I recently developed a library specifically designed to extract server-side rendered environment variables with ease. This library offers a customizable base class for extension. For brevity, the method getEnvironmentValues() has been excluded: @Directive ...

Using the @for directive with Angular's async pipe

I am currently working with the latest version of Angular, which is 18.1.0, and I want to utilize the async pipe for an array of countries that are fetched from the backend using the HTTP client. However, when I try to use the new Angular feature of @for, ...