【发布时间】:2019-07-18 18:34:02
【问题描述】:
我正在尝试在我的项目中实现一个保护,它应该等到 ngrx-store 的加载完成并且在此检查之后是否经过用户身份验证。问题是,守卫没有等待商店加载完成。
我的 app-routing.module.ts:
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import {
IsAuthGuard,
HomeRedirectGuard
} from '@app/core';
import { LoginComponent } from './static';
const routes: Routes = [
{
path: '',
redirectTo: 'home',
pathMatch: 'full',
},
{
path: 'settings',
loadChildren: 'app/features/settings/settings.module#SettingsModule',
canActivate: [IsAuthGuard, HomeRedirectGuard]
},
{
path: 'login',
component: LoginComponent,
data: { title: 'tts.menu.login' }
},
{
path: 'home',
loadChildren: 'app/features/home/home.module#HomeModule',
data: { title: 'tts.menu.home' },
canActivate: [IsAuthGuard, HomeRedirectGuard]
}
{
path: '**',
redirectTo: 'home'
}
];
@NgModule({
// useHash supports github.io demo page, remove in your app
imports: [
RouterModule.forRoot(routes, {
useHash: true,
scrollPositionRestoration: 'enabled'
})
],
exports: [RouterModule]
})
export class AppRoutingModule { }
IsAuthGuard 的想法只是检查我们是否有认证,如果没有认证则发送登录请求动作。
IsAuthGuard:
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlSegment, CanLoad, Route } from '@angular/router';
import { Observable, of } from 'rxjs';
import { Store, select } from '@ngrx/store';
import { selectAuthisAuthenticated } from '@app/root-store/auth-store/selectors';
import { AuthStoreActions } from '@app/root-store';
import { take, switchMap } from 'rxjs/operators';
@Injectable()
export class IsAuthGuard implements CanActivate, CanLoad {
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | Observable<boolean> {
return this.canLoad(route.routeConfig, null);
}
constructor(private store: Store<any>, private router: Router) { }
canLoad(route: Route, segments: UrlSegment[]): Observable<boolean> | boolean {
console.log("CanLoad isAuth");
return this.store
.pipe(select(selectAuthisAuthenticated),
take(1),
switchMap(isAuth => {
if (!isAuth) {
this.store.dispatch(new AuthStoreActions.AutoLoginRequestAction());
}
return of(true);
}));
}
}
最后是我的 HomeRedirectGuard 服务,它不起作用:
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
import { Observable, Subject } from 'rxjs';
import { Store, select } from '@ngrx/store';
import { selectAuthUser, selectAuthIsLoading} from '@app/root-store/auth-store/selectors';
import { Constants } from '../constants/constants.enum';
import { takeUntil, last, map } from 'rxjs/operators';
@Injectable()
export class HomeRedirectGuard implements CanActivate{
isUser = false;
private unsubscribe$: Subject<void> = new Subject<void>();
constructor(private store: Store<any>, private router: Router) {
this.store
.pipe(select(selectAuthUser),
takeUntil(this.unsubscribe$))
.subscribe(user => {
this.isUser = !!user;
console.log("USER =", user);
});
}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | Observable<boolean> {
return this.checkAuth();
}
checkAuth(): Observable<boolean> | boolean {
console.log("CanLoad Home");
return this.store.pipe(select(selectAuthIsLoading),
last(val => val === false),
map(isLoading => {
console.log("isLoading = ", isLoading);
console.log("isUser = ", this.isUser);
let redirectUrl;
if (this.isUser) {
redirectUrl = Constants.HOME_URL;
} else {
redirectUrl = Constants.LOGIN_URL;
}
this.router.navigate([redirectUrl]);
console.log("HOME redirectUrl=", redirectUrl);
return true;
})
);
}
}
我在控制台中看到: enter image description here
CanLoad isAuth
[DEBUG] 操作:[Auth] 自动登录请求 {payload: undefined, oldState: {…}, newState: auth: {isAuthenticated: false, user: null, redirectUrl: null, error: null, isLoading: true} ...
USER = null
可以加载主页
[DEBUG] 操作:[Auth] 自动登录失败 {payload: undefined, oldState: {…}, newState: auth: {isAuthenticated: false, user: null, redirectUrl: null, error: null, isLoading: false}
所以,我来到 HomeRedirectGuard,但 Guard 不等待 select 的最后一个发射,其中 isLoading 为 false 并且存储中有信息,是否有身份验证。
【问题讨论】:
-
@MauroDias 谢谢,我已经用
filter((authState) => !authState.isLoading)修复了它
标签: angular typescript angular-router-guards