【问题标题】:angular2 guard not working on page refreshangular2 守卫在页面刷新时不起作用
【发布时间】:2017-12-28 13:45:07
【问题描述】:

在每次请求之前,我都想确保有可用的用户配置文件。我使用 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());
  }

当我浏览菜单(&lt;a&gt; 和 routeLink)时,console.log('profile loaded') 有效。但是如果我用 f5 或通过浏览器重新加载页面,它永远不会到达那里..

console.log('load') 总是被执行。

编辑:

如果我在canActivateChild返回:

return Observable.of(true).map(() => {
  console.log('Test');
  return true;
});

它工作正常...我得到console.log('test')

【问题讨论】:

  • 在 F12 浏览器控制台的网络选项卡上,看到对 /profile 的请求了吗,是否成功?
  • 这是一个有趣的问题。如果您只返回Observable.of(true) 而不是调用this.profileService.loadProfile(),事情会按预期工作吗?
  • 如果可能的话,你能不能试试 plnkr ,那样你会很快得到帮助。您可以将虚拟数据用于 HTTP 调用
  • @HendrikBrummermann 是的,请求已经发出,并且使用正确的数据也成功
  • 如果你在canActivateChild() 内部console.log(而不是在 Observable 链本身),它可以工作吗?

标签: angular angular2-routing observable angular2-observables angular2-guards


【解决方案1】:

我认为它在您收到响应之前已解决,请尝试添加一个重播主题,一旦您的请求返回,该主题将解析为真或假

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

【讨论】:

    【解决方案2】:

    我在 @angular/router 的 RC 上运行。在我更新它之后,它像预期的那样工作。

    【讨论】:

      猜你喜欢
      • 2012-03-15
      • 2015-02-16
      • 2022-01-16
      • 1970-01-01
      • 1970-01-01
      • 2016-08-07
      • 2023-03-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多