在每个请求之前,我想确保有可用的用户配置文件.我使用canActivateChild防护来做到这一点.
根据angular2的文档,可以返回一个observable:https://angular.io/api/router/CanActivateChild
app.routes.ts
export const routes: Routes = [ { path: '',canActivateChild: [ProfileGuard],children: [ { path: 'home',component: HomeComponent,canActivate: [AuthGuard] },{ path: 'login',component: LoginComponent,canActivate: [GuestGuard] },} ];
canActivatedChild在子路径canActivate之前执行
profile.guard.ts:
export class ProfileGuard implements CanActivateChild { constructor(private profileService: ProfileService,private snackbar: MdSnackBar) { } canActivateChild(childRoute: ActivatedRouteSnapshot,state: RouterStateSnapshot): boolean | Observable<boolean> { if (this.profileService.user == null && localStorage.getItem('__token') != null) { return this.profileService.loadProfile().map((user) => { console.log('profile loaded'); this.profileService.user = <UserModel>user.data; return true; }); } return true; } }
public loadProfile(): Observable<any> { console.log('load'); return this.http.get('/profile').map(res => res.json()); }
当我浏览菜单(< a> with routeLink)时,console.log(‘profile loaded’)可以正常工作.但是,如果我用f5或通过浏览器重新加载页面,它永远不会到达那里..
始终执行console.log(‘load’).
编辑:
如果我在canActivateChild返回:
return Observable.of(true).map(() => { console.log('Test'); return true; });
它运行正常…我得到console.log(‘test’)
解决方法
我认为它会在您收到回复之前解决,尝试添加一个重播主题,一旦您的请求返回,该主题将解析为true或false
import {Observable,ReplaySubject} from 'rxjs/Rx'; public loadProfile(): Observable<any> { console.log('loading profile'); return this.http.get('/profile').map(res => res.json()); } public isUserLoggedInObs(): Observable<boolean> { const userLoggedIn: ReplaySubject<boolean> = new ReplaySubject<boolean>; this.loadProfile.first().subscribe( user => userLoggedIn.next(user.loggedIn === true) ) return userLoggedIn.asObservable(); } canActivateChild(childRoute: ActivatedRouteSnapshot,state: RouterStateSnapshot): boolean | Observable<boolean> { return this.profileService.isUserLoggedInObs() }