4

我正在使用Observable<boolean>退货canActivate()。为测试设置了以下功能,它正确解析,组件显示。

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
  return Observable.from([{ admin: true }]).map(x =>
  {
    if (x.admin) return true;
    return false;
  });
}

但是,实际代码的行为是,尽管控制台输出指示应该激活路由,但我仍停留在登录组件上。与上述测试的唯一真正区别是我调用的是服务this.auth.isAdmin()而不是使用Observable.from. 的结果this.auth.isAdmin()Observable<boolean>一个值为真。

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
  const isAdmin$ = this.auth.isAdmin();
  return isAdmin$.map(x =>
  {
    console.log('isAdmin returned ' + x);
    if (!x) {
      console.log('redirectToLogin');
      this.auth.redirectToLogin(state.url);
      return false;
    } else {
      console.log('canActivate = true');
      return true;
    }
  });  
}

这是路由:

{
  path: 'admin',
  canActivate: [AdminGuard],
  children: [
    ...adminRoutes
  ]
},

这是我的控制台输出:

isAdmin returned false
admin-guard.service.ts:27redirectToLogin
auth.service.ts:36 navigating to stored path "/admin"
auth.service.ts:21 Object {isAdmin: true, isPaid: false, $key: "xYFs8kMDpKdYKxDw4AL21FtnSWn1"}
admin-guard.service.ts:25 isAdmin returned true
admin-guard.service.ts:31 canActivate = true

如果感兴趣,这里是 isAdmin() 函数:

isAdmin(): Observable<boolean> {
    if (!this.auth) return Observable.from([false]);
    const uid = this.auth.uid;
    return this.af.database.object(`user/${uid}`).do(x => console.log(x)).map(x => x.isAdmin);
}
4

1 回答 1

7

isAdmin您的函数返回的 observable未完成。AngularFire2FirebaseObjectObservable实例未完成;它们在底层数据更改时发出对象。

守卫返回的 Observables 必须完成。您可以通过在发出第一个值时使用first(或) 来完成 observable 来确保这一点:take(1)

canActivate(
  route: ActivatedRouteSnapshot,
  state: RouterStateSnapshot
): Observable<boolean> {
  const isAdmin$ = this.auth.isAdmin();
  return isAdmin$.first().map(x =>
  {
    console.log('isAdmin returned ' + x);
    if (!x) {
      console.log('redirectToLogin');
      this.auth.redirectToLogin(state.url);
      return false;
    } else {
      console.log('canActivate = true');
      return true;
    }
  });  
}

在撰写本文时,返回的 observable 必须完成。但是,Angular 现在调用 返回的 observable,因此不再需要 observable 完成。first

于 2016-09-12T02:27:25.413 回答