-1

I have a problem, how to combine 2 observable in a complicated case. I show you the code as follow:

so I have 2 Observables: This 2 Observable will be used in canActivate(): Observable<boolean| UrlTree>

1: this.loadingState : Observable<LoadingState>
2: currentData : Observable<currentData>

so loadingState will return the state of loaded data, either everything ok, or error. in my case I will check firstly the loadingState, if everything is ok, if not, will return to error page. If everything is ok, then I will pipe to currentData and do some check in currentData.

my first code as follow, but it is not working

return this.loadingState.pipe(
 map((loadingState) => {       // operator function 1
   if(loadingState.error){
      // then return something.
   }
}),

 () => {                      // operator function 2
  this.currentData.pipe(
   map((currentData) => {
     // here will check current, also return something.
   })

  );
}

);

this first problem is: the first map loadingState is not all code path return a value. my idea is, if loadingState.error is true, the oerator function 2 will not carried out.

I have googled also some solution such as with combineLatest or forkjson, It could also not work.

maybe you have some solution

best thx

3
  • Please elaborate on "is not working". Also the code provided seems to be syntactically wrong, please share as much of it as you can so we understand what you tried so far. Commented Mar 16, 2023 at 7:49
  • You may rather want to use the operator SwitchMap to do that. Commented Mar 16, 2023 at 8:09
  • can you give me example with my code? Commented Mar 16, 2023 at 8:13

2 Answers 2

0

We could use switchMap to switch to the other observable when error is false.

import { Component, OnDestroy, OnInit } from '@angular/core';
import { map, Observable, of, Subject, switchMap, takeUntil } from 'rxjs';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit, OnDestroy {
  loadingState$: Observable<any> = of({ error: false });
  currentData$: Observable<any> = of({ data: 'data' });
  destroyed$: Subject<void> = new Subject();

  ngOnInit() {
    this.loadingState$
      .pipe(
        takeUntil(this.destroyed$),
        switchMap((loadingState) => {
          if (!loadingState.error) {
            return this.currentData$.pipe(
              map((currentData) => {
                console.log('loadingState error was false, switch to current data');
                console.log(currentData);
              })
            );
          } else {
            // loadingState.error is ture here, do something?
          }
        })
      )
      .subscribe();
  }

  ngOnDestroy() {
    this.destroyed$.next();
  }
}

Example: https://stackblitz.com/edit/angular-ivy-gjkulg?file=src%2Fapp%2Fapp.component.ts

Sign up to request clarification or add additional context in comments.

2 Comments

that seems like gut, but I have a problem to use it, becase I use this code in a canActivate with return value UrlTree or Boolean. the loadingState return a observable LoadingState
Please provide a full explanation with more relevant code. Your question did not cover that you wanted to use an Observable for an authGuard canActivate
0

Something like the following may work in your use case. Unclear what the requirements are though.

tap can be used for side effects and this won't affect the rest of the stream - use sparingly!

const isError$ = this.loadingState.pipe(
  map(loadingState => !!loadingState.error),
  tap(isError => {
    // return to error page
  })
)

filter "stops" emissions from it's source depending on the predicate

// combine 2 observables
combineLatest([isError$, currentData]).pipe(
  // if loadingState.error is true, the operator function 2 will not carried out
  filter(([isError, data]) => !isError),

  // continue
  map(([_, data]) => {
    
  }),

)

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.