I observed strange behavior with my CanActivate guard (Angular 10.2.5):
export class VersionGuardService implements CanActivate {
constructor(private router: Router, private http: HttpClient){
}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
console.log("In the Guard");
return this.http.request<any>('get',`https://jsonplaceholder.typicode.com/users`).pipe(
tap(resp => console.log("Response: ", resp)),
map(resp => false)
);
//return of(false);
}
}
Routes in app-routing.module.ts looks like this:
const routes: Routes = [
{
path: 'login',
component: LoginComponent,
canActivate: [VersionGuardService]
},
{
path: 'logout',
component: LogoutComponent
},
{
path: 'error',
component: ErrorComponent
},
{
path: '',
redirectTo: 'login',
pathMatch: 'full'
}
];
If i invoke app with above code i got Too many calls to Location or History APIs within a short timeframe
error (in Firefox). When I inspect console output in the browser - indeed there is a lot of (nearly 200) entries with In the Guard
message. If I inspect the network tab in dev tools i see a lot of invokation of GET on remote service https://jsonplaceholder.typicode.com/users
with NS_BINDING_ABORTED
message in the "Transferred" column in network dev tools tab.
Edit 1 The stream from http call does not provides any data (No entry beginning with "Response: " in console log. So it is not issue with how pipe after http call is constructed.
The question is why is this happening? What causes the canActivate method execute more than one time?
For example if I remove http call and leave it like this:
@Injectable()
export class VersionGuardService implements CanActivate {
constructor(private router: Router, private http: HttpClient){
}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
console.log("In the Guard");
return of(false);
}
}
It works as expected (only one entry 'In the Guard` in the Firefox console).
The reason why I want to use Guard is to check app version compatibility (with backend services) on website initialization and decide whatever load login window or redirect to error message site.
Edit 2 If I move guard into "later" link in Routes (i mean: the link which is executed later in the app) and guard works as expected. So I though it an is issue with app initialization, so I prepared stackblitz with guard on first link: https://stackblitz.com/edit/angular-ivy-qgfdk3 And it also works as expected.
Thanks in advance for any help!