I am writing a code that check if the browser has userInfo. If not, the browser calls an API to get the userInfo from server. Only if there is a valid userInfo, the user is allowed to navigate to the pages.
My problem is that canactivate() does not wait for the call to complete. I've tried Resolver which are mentioned in other threads, but it also didn't work.
So, I put async-await but it is also not working. canactivate() returns before getUser() is completed. Is the syntax of async-await is wrong in the below code?
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private router: Router, private refService: RefService, private userInfoService: UserInfoService) {
}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
this.getUser();
console.info('canActivate completed');
return this.userInfoService.getUserInfo() !== null;
}
async getUser() {
if(!this.userInfoService.getUserInfo()) {
await this.refService.getTamUser().toPromise( ).then(data => {
this.userInfoService.setUserInfo(data);
});
}
}
}
can Activate is not (a)waiting for getUser. I would do it like this:
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
const userInfo = this.userInfoService.getUserInfo()
if (userInfo) {
return userInfo !== null;
} else {
return this.refService.getTamUser().pipe(switchMap((data: any) => {
this.userInfoService.setUserInfo(data);
return of(data !== null);
}))
}
}
First check if the user info is present. If not then get the user info from ref service and return a new observable of type boolean. A false boolean means either not allowed to access or refService call failed.
Read more about switchMap here. In short words: Make a new observable out of data from the original observable.
You can wrap your async logic inside the canActivate function itself as a promise, so that can canActivate will return only in the then or catch block of promise return. Do return as an observable.
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private router: Router, private refService: RefService, private userInfoService: UserInfoService) {
}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
if (!this.userInfoService.getUserInfo()) {
this.refService.getTamUser().toPromise()
.then(data => {
if (data) {
this.userInfoService.setUserInfo(data);
console.info('canActivate completed');
return of(true);
} else {
return false
}
})
.catch(() => {
return false;
})
} else {
return of(this.userInfoService.getUserInfo() !== null);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With