5
votes

I have a situation where there is an auth guard and all routes are below it.

The auth service determines if the user is logged in or not by sending a request to the backend

private subject = new BehaviorSubject<User>(undefined)

  user$: Observable<User> = this.subject.asObservable().filter(user => !!user)

  isLoggedIn$: Observable<boolean> = this.user$.map(user => !!user.id)

constructor (private http: HttpClient) {
    http.get<User>(API['AUTH']['GET_AUTHENTICATED_USER'])
      .do(console.log)
      .subscribe(user => this.subject.next(user ? user : ANONYMOUS_USER))
  }

However auth guard does not seem to wait for the request to finish and gets a boolean false as the predefined value of (isLoggedIn$ observable)

auth guard

constructor (private authService: AuthService, private router: Router) {
    this.authService.isLoggedIn$.subscribe(isLoggedIn => this.isLoggedIn = isLoggedIn)
  }

is there a way to wait until the request completes or at least get the second value emitted through the observable?

1
Rather than subscribe to the observable in the guard, which makes no sense anyway, since you shouldn't be subscribing to something when you only just want to get a value once, you should instead call a method which does the check and returns true or false. - David Anthony Acosta
If your guard implements CanActivate or CanLoad then you should have a method canActivate or canLoad respectively that returns Observable<boolean>. You shouldn't need to subscribe. - bygrace

1 Answers

6
votes

I believe the problem might come from using Behavioursubject here. From the docs:

Observers can subscribe to the subject to receive the last (or initial) value and all subsequent notifications.

As you'll see this means that you will receive data as soon as you subscribe, if there is a default value set.

Fortunately, the docs then offer:

If you are looking for BehaviorSubject without initial value see Rx.ReplaySubject

ReplaySubject doesn't send the initial value like BehaviourSubject does, though it does still offer the benefit of being able to subscribe 'late' and still receive the latest event.

BehaviorSubject and ReplaySubject docs.