简体   繁体   English

如何使canActivate等待商店加载

[英]How to make canActivate to wait for store loading

I'm trying to implement a guard in my project, that should wait until ngrx-store's loading complete and after this check is user authenticated or not. 我正在尝试在我的项目中实施防护措施,该防护措施应等到ngrx-store的加载完成以及此验证是否通过用户验证之后再进行。 The problem, that guard doesn't wait completion of store's loading. 问题是,守卫不等待商店加载完成。

My app-routing.module.ts: 我的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 { } 

The idea of IsAuthGuard is just check if we have authentication or not, and dispatch login request action if not authenticated. IsAuthGuard的思想是检查我们是否已通过身份验证,如果未通过身份验证,则调度登录请求操作。

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); })); } } 

And finally my HomeRedirectGuard service, that doesn't work: 最后,我的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; }) ); } } 

And I see in console this: enter image description here 我在控制台中看到: 在此处输入图片描述

CanLoad isAuth CanLoad isAuth

[DEBUG] action: [Auth] Auto login request {payload: undefined, oldState: {…}, newState: auth: {isAuthenticated: false, user: null, redirectUrl: null, error: null, isLoading: true } ... [DEBUG]操作:[Auth]自动登录请求{有效载荷:未定义,oldState:{…},newState:auth:{isAuthenticated:false,用户:null,redirectUrl:null,错误:null, isLoading:true } ...

USER = null USER =空

CanLoad Home 可以加载首页

[DEBUG] action: [Auth] Auto login failure {payload: undefined, oldState: {…}, newState: auth: {isAuthenticated: false, user: null, redirectUrl: null, error: null, isLoading: false } [DEBUG]操作:[Auth]自动登录失败{有效载荷:未定义,oldState:{…},newState:auth:{isAuthenticated:false,用户:null,redirectUrl:null,错误:null, isLoading:false }

So, I come to HomeRedirectGuard, but Guard doesn't wait last emission of select, where isLoading is false and there are information in store, are there authentication or not. 因此,我来​​了HomeRedirectGuard,但Guard并不等待上一次发出的select,其中isLoading为false且存储中有信息,是否有身份验证。

You can add a skipWhile: 您可以添加一个skipWhile:

this.store.pipe(select(selectAuthIsLoading),
skipWhile(loading => !loading),
...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM