2

I am learning RxJS. I have 2 api, based on data of 1st api, I have to call second api and return the value. I did with subscribe() method like this:

checkPermission(permissionName: string): Observable<boolean> {
    this.checkCompanySettingForPermission(
      this.pageLevelCompanySettingName
    ).subscribe(res => {
      const shouldCheck = res.Value;
      if (shouldCheck.toLowerCase() === "true") {
        this.hasPermission(permissionName).subscribe(res => {
          this.$permissionSub.next(res.permission);
        });
      } else {
        this.$permissionSub.next(true);
      }
    });
    return this.$permissionSub.asObservable();
  }

I want to avoid subscribe() method in another subscribe() method. Can I do with any operator of RxJS?

I tried it with switchMap() also but getting lots of syntax error. Please help.

13
  • Hello! Why are you hesitant to use nested subscribe method? You can always unsubscribe when you're finished. Commented Sep 2, 2021 at 15:20
  • @AliCelebi actully my seniors want me to don't use subscribe in another subscribe, and I am trying it from last 3 hrs. But not getting solution. Commented Sep 2, 2021 at 15:21
  • Please see the following example where this type of question was asked. I hope it would be useful for you. stackoverflow.com/questions/58717372/… Commented Sep 2, 2021 at 15:24
  • @AliCelebi tried so many things, but not getting any solution. Please help if you can. Last hope Commented Sep 2, 2021 at 15:27
  • I think you're looking for mergeMap Commented Sep 2, 2021 at 15:37

2 Answers 2

1

You can achieve that using one of the Higher-Order RxJS mapping operators such as: switchMap, mergeMap, concatMap, merge the source observable with the new one.

So if we go with switchMap or mergeMap in your case we should return at the end a new observable to be merged with the original one checkCompanySettingForPermission.

If the condition is true, will return the this.hasPermission observable, else will return a new observable using of function with the value we need to pass (true in your case).

You can try the following:

checkPermission(permissionName: string): Observable<boolean> {
  this.checkCompanySettingForPermission(this.pageLevelCompanySettingName)
    .pipe(
      switchMap(res => {
        const shouldCheck = res.Value;
        if (shouldCheck.toLowerCase() === 'true') {
          // switchMap to the new observable, then map it to return only the permission.
          return this.hasPermission(permissionName).pipe(
            tap(result => {
              // do some stuff with the result before mapping it to the `result.permission`
            }),
            map(result => result.permission)
          );
        } else {
          // return observable of true, to be handled within subscribe.
          return of(true);
        }
      })
    )
    .subscribe(permission => this.$permissionSub.next(permission));

  return this.$permissionSub.asObservable();
}

And if you don't use the this.$permissionSub elsewhere, you can remove it from the method above, and return this.checkCompanySettingForPermission(....) without subscribe, then you can call this method in your component like the following:

// Example
this.service.checkPermission(addPermission).subscribe((value) => {
   console.log(value)
})
Sign up to request clarification or add additional context in comments.

8 Comments

getting error => You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
I think It should work, please check it again.
I am debugging your solution, trying it, but not getting the actual reason, because it is working when " if (shouldCheck.toLowerCase() === 'true')" , otherwise giving me an error
Sorry, my bad, just add return before of(true).
Or you can use tap operator
|
0

Try this format.

checkPermission(permissionName: string): Observable<boolean> {
  this.checkCompanySettingForPermission(this.pageLevelCompanySettingName)
    .pipe(
      map(res => res?.Value.toLowerCase() === 'true'
          ? this.hasPermission(permissionName).pipe(
               map(result => result.permission)
            )
          : of(true)

       ),
      switchMap(ob => ob)
    )
    .subscribe(permission => this.$permissionSub.next(permission));

  return this.$permissionSub.asObservable();
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.