I've seen a few answers on SO regarding this same topic, but I believe in Angular 13.x the behavior is different. In the below code, canActivate needs to return an observable boolean. So all code paths MUST return an observable boolean, if I remove this line:
return of(valid); // always hits first
I get a compile error:
error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.
This makes sense. I need to return an observable boolean. However I am still unsure how to have canActivate
wait for this.authService.authCheck()
to return the response?
Here is what I tried:
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router';
import { Observable, of, map, catchError, observable } from 'rxjs';
import { AuthService } from '../data/auth.service';
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) { }
canActivate(
route: ActivatedRouteSnapshot): Observable<boolean> {
var valid = false;
this.authService.authCheck().subscribe(response => {
if (!response) {
this.router.navigateByUrl('login');
valid = false;
return valid;
} else {
valid = true;
return valid;
}
});
return of(valid); // always hits first
}
}
I have tried map also
canActivate(route: ActivatedRouteSnapshot): Observable<boolean> {
this.authService.authCheck().pipe(map(r => {
if (!r) {
console.log("failure");
this.router.navigateByUrl('login');
return false;
} else {
return true;
}
})); // error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.
}
CodePudding user response:
You should return Observable
so your first approach with the subscribe
is not correct. You were pretty close with the second one - you're missing return
.
Following code should work:
canActivate(route: ActivatedRouteSnapshot): Observable<boolean> {
return this.authService.authCheck().pipe(map(r => {
if (!r) {
console.log("failure");
this.router.navigateByUrl('login');
return false;
} else {
return true;
}
}));