Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular - How to make canActivate to await for promise response?

I try to check in CanActivate gurad if user is logged in.
If yes, then I navigate him to some page.
If not, then I navigate him to login page.
I use promise.

I have a service named LoginService:

export class LoginService {

  urlcheck = 'http://localhost:80/isconnected.php';
  resultCheck;

  constructor(private http: HttpClient, private router: Router)
  {
  }

  async checkLogin()
  {
    const x = await this.updateConnectedState();
    return x;
  }

  updateConnectedState()
  {
    //formData here...
    return this.http.post(this.urlcheck, formData).toPromise()
      .then(
        (response) =>
        {
          this.resultCheck = response; 
          console.log(response);
          return this.resultCheck.state; //state is true/false
        },
        (error) => 
        { 
            console.log(error); 
            return false;  
        }
      );
    }
  }


the canActivate Gurad:

export class BackHomeGuardService implements CanActivate
{
  constructor(private logService: LoginService, private router: Router)
  {
  }

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean>|boolean
  {
    const result = this.logService.checkLogin();
    console.log( result);

    if (result)
    {
      console.log('true');
      // navigate to hom page
      return true;
    }
    else
    {
      console.log('false');
      // navigate to login page
      return false;
    }
  }
}

The guard canActivate function always return true.
I checked in console and the the promise result is:

__zone_symbol__state: null
__zone_symbol__value: []

I want to make the canActive await for result before it will do something.
What if my backend (php code file) will take 30 seconds to be completed?
I need a solution. Thanks.

like image 277
matan___4 Avatar asked Dec 01 '25 14:12

matan___4


1 Answers

According to CanActivate's type:

export declare interface CanActivate {
    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree;
}

the method canActivate can return Observable, Promise or boolean.

You can simply return your checkLogin() call like:

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean>|boolean {
    return this.logService.checkLogin();
}

and everything will work.


UPDATE

answering the question "how do I handle the returned boolean in my canActivate" from comments

The idea of the CanActivate is to restrict the access to some routes due to a certain condition. You can perform some side-effects (but I'm not sure how they will be displayed, unless it's a console.log) by chaining your Promise or Observable:

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean>|boolean {
    return this.logService
      .checkLogin()
      .then(canLogin => {
         console.log('Can user login:', canLogin);
         // perform you side effects here
      })

}
like image 65
Yevhenii Dovhaniuk Avatar answered Dec 03 '25 05:12

Yevhenii Dovhaniuk



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!