7

I am new in Angular, I need to implement a function that returns true/false, I going to use the return in canActivate guard, but this function consumes a api by http.get, so like the communication is asynchronous this function always return FALSE, because http.get yet is in process.

My class guard:

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {

    let url: string = state.url;


    if (this.loginService.isLoggedIn()) {
        return true;
    }

    this.loginService.redirectUrl = url;

    this.router.navigate(['login']);

    return false;
}

and function isLoggedIn()

isLoggedIn() {

    let logged: boolean = false;

    this.http.get('api/values', this.httpService.headers())
        .map((res: Response) => {
            logged = res.json();
        });

    return logged;

}

I read many questions, but I don't found the answer.

Rit
  • 98
  • 1
  • 1
  • 7

1 Answers1

8

guard typings says it can return

Observable<boolean>, Promise<boolean> or boolean

so change isLoggedIn to:

isLoggedIn() {

  return this.http.get('api/values', this.httpService.headers())
    .take(1)
    .map((res: Response) => res.json());
}    

update

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    let url: string = state.url;

    return this.isLoggedIn().map(loggedIn => {
      if(!loggedIn) {
        this.loginService.redirectUrl = url;
        this.router.navigate(['login']);
      }
      return loggedIn;
    }
}
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
kit
  • 4,890
  • 3
  • 24
  • 23
  • thanks Kit, but this way not call my api. if I change to: return this.http.get('api/values', this.httpService.headers()).subscribe(res => res.json()) my api is call, however res.json() isn't returned as value of function, how to return the result of subscribe as value of function – Rit Sep 29 '16 at 16:57
  • I edited my answer. In map() I didn't return value. Now it should work. Do not call subscribe() as it returns Subscribtion not Observable. – kit Sep 29 '16 at 19:50
  • 2
    AFAIK you still need to add `.first()` or `.take(1)` at the end so the observable closes after the first event. Otherwise the router waits forever. – Günter Zöchbauer Sep 29 '16 at 20:10
  • Thanks @GünterZöchbauer – kit Sep 29 '16 at 21:21
  • I'm sorry, but this way don't work. looks that only .map doesn't run the api. If I to use this way, I have that to call isLoggerIn() with subscribe: if (this.loginService.isLoggedIn().subscribe( .... )) { }. I didn't understand how to work .map, .subscribe .... Why http.get need these? – Rit Sep 30 '16 at 01:11
  • 2
    Observables are lazy and don't do anything until `subsribe()` is called. When the observable is returned from `canActivate` the router calls `subsribe()` – Günter Zöchbauer Sep 30 '16 at 03:04
  • Got it @GünterZöchbauer, it works if I change my canActivate to: canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { return this.loginService.isLoggedIn(); } , however I'm not redirected to LoginComponent, how could be implemented correctly the canActivate? – Rit Sep 30 '16 at 12:10