2

I have code with subscribe inside subscribe:

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);
    }
);

How can I optimize it in RxJS 5?

koral
  • 2,807
  • 3
  • 37
  • 65
  • 1
    Use `mergeMap` or `concatMap` instead of the first `subscribe` – martin Jan 08 '19 at 10:41
  • What goga said ... you should never need to nest subscriptions. This might help you: https://blog.strongbrew.io/rxjs-best-practices-in-angular/ – Davy Jan 09 '19 at 12:53

1 Answers1

4

Please don't use subscribe inside another subscribe. Using native RxJS operators, there is better way around this which will be:

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) => {
          // this catcherror will happen if update3 failes
          return merge(
            // revert changes made to update2
            this.http.post('/update2', previousValues),
            // revert changes made to update1
            this.http.post('/update1', previousValues),
          );
        }),
      ),
    ),
    catchError((err) => {
      // this catcherror will happen if update2 failes
      // revert changes made to update1
      return this.http.post('/update1', previousValues);
    }),
  )
  .subscribe(
    (result) => {
      console.log(result);
    },
    (err) => {
      // this error will happen if an error happens wich is not caught
      console.log(err);
    },
  );

This way you only have one subscribe method to handle last remaining result if you want to.

Keep in mind that catchError() inside pipe will be trigerred if exception is fired prior to it anywhere. If exception is handled already, by the handler, same exact exception will not trigger other catchError() twice.

Goga Koreli
  • 2,807
  • 1
  • 12
  • 31