Angular Rxjs Manage Nested Subscriptions

100 views Asked by At

Hi I've a function which has nested subscriptions.

  public loadUser(): Observable<string> {
    return this.getUser().subscribe(
      (userResponse: any) => {
        if (userResponse) {
          this.userId = userResponse.toLowerCase();
          this.getAppSupportUsersList();
          this.getUserEntitlements().subscribe((response: any) => {
            localStorage.setItem('UserEntitlements', JSON.stringify(response));
            this.processUIEntitlements(response);
            this.getUserDetails(this.userId).subscribe((userDetails) => {
              this.userInfo = userDetails;
              this.setUserName();
            });
          });
        }
      },
      (error) => {
        console.error(error);
      }
    );
  }

I'm not sure how can we avoid nesting of subscriptions. Is there a better way to rewrite the nested subscriptions using switchMap() or mergeMap()?

2

There are 2 answers

4
IDK4real On BEST ANSWER

This can be re-written with a rxjs switchMap or a map, depending on how you want to handle multiple requests.

If only the latest counts, which seems to be the most indicated since you are writing to the local storage, go with the switchMap approach.

public loadUser(): Observable<string> {
  return this.getUser().pipe(
    filter(val => !!val),
    switchMap(userResponse => {
      this.userId = userResponse.toLowerCase();
      this.getAppSupportUsersList();
      return this.getUserEntitlements();
    }),
    switchMap(response => {
      localStorage.setItem('UserEntitlements', JSON.stringify(response));
      this.processUIEntitlements(response);
      return this.getUserDetails(this.userId);
    }),
    .map(userDetails => {
      this.userInfo = userDetails;
      this.setUserName();
      return JSON.stringify(userDetails);
    })
  );
}     
6
Naren Murali On

We can use switchMap, since we just want to chain subscriptions, switch to another after the previous is done.

  public loadUser(): Observable<string> {
    return this.getUser().pipe(
      switchMap((userResponse: any) => {
        if (userResponse) {
          this.userId = userResponse.toLowerCase();
          this.getAppSupportUsersList();
          return this.getUserEntitlements().pipe(
            switchMap((response: any) => {
              localStorage.setItem('UserEntitlements', JSON.stringify(response));
              this.processUIEntitlements(response);
              return this.getUserDetails(this.userId).pipe(
                tap((userDetails) => {
                  this.userInfo = userDetails;
                  this.setUserName();
                })
              )
            })
          );
        }
        return of(null);
      })
    );
  }

  callingFunction() {
      this.loadUser().subscribe({
        next: (next) => {
          console.error(next);
        },
        error: (error) => {
          console.error(error);
        }
      });
  }