0

我将 Ionic 与 Angular 一起使用。在我的一个路由守卫中,我需要查看是否创建了 Firestore 文档并为其返回一个布尔值,这需要一些时间才能从服务器获得响应,但是路由守卫不会等待该值返回并正常运行,因此页面不受保护!我怎样才能让路由守卫等待值?或者,在路由保护运行之前返回值?这是我向firestore发送请求的地方:

export class FirebaseService {

  ex: Promise<boolean>;
  categoryDone: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
  constructor(private afs: AngularFirestore) {
    this.ex = new Promise((resolve) => {
          this.afs.collection('users').doc(this.user.uid).collection('categories').get().toPromise().then(
            data => {
              if (data.size > 0) {
                resolve(true)
              } else {
                resolve(false)
              }
            }
          )
        })
        this.ex.then(data=>{
          if (data) {
            this.categoryDone.next(true)
          } else {
            this.categoryDone.next(false)
          }
        })
  }

这是我的路由保护代码,我将它用于我的页面:

export class CategoryDoneGuard implements CanActivate {
  categoryDone: boolean;
  constructor(private router: Router, private firebaseService: FirebaseService) {
    this.firebaseService.categoryDone.asObservable().subscribe(
      categoryDone => this.categoryDone = categoryDone
    )
  }
  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean> | boolean {
      console.log(this.categoryDone,"Category Done VAriable in CategoryDoneGuard")
      setTimeout(() => {
        console.log(this.categoryDone,"Catgeory") //true because i waited 1 second
      }, 1000);
    if (!this.categoryDone) { //variable is undefined here 
      console.log('You are in InfoDoneGuard')
      return true
    }
    this.router.navigate(['tabs/tab-profile'])
    return false
  }

}
4

2 回答 2

2

就像在其他答案中一样,auth guard 可以接受布尔值、可观察值或布尔值或 urltree 的承诺。但我会稍微重构整个服务功能,除非你需要categoryDone其他东西,但如果你需要的话,无论如何你都可以在你的服务中添加它。

但是,当您的服务当前存在时,您正在调用toPromise()但也创建了一个新的承诺,这实际上没有任何意义。

我会做...

服务:

// please choose a more suitable name :D 
getBool() {
  return this.afs.collection('users').doc(this.user.uid).collection('categories').get().pipe(
    map(data => data.size > 0),
    // if you need
    // tap(bool => this.categoryDone.next(bool))
  )
}

可以激活:

canActivate(...): Observable<boolean> {
  return this.firebaseService.getBool().pipe(
    map(bool => {
      if (bool) {
        return true;
      }
      this.router.navigate(['tabs/tab-profile'])
      return false;
    })
  )
}

但是,如果categoryDone在您的应用程序中对您来说是必不可少的,您也可以在 authguard 中订阅它,就像在 MoxxiManagarm 的回答中一样。无论如何,我会重组 firebase 查询以删除承诺的东西。

于 2019-11-16T19:39:53.947 回答
0

不要返回布尔值,返回 Observable!

导出类 CategoryDoneGuard 实现 CanActivate {

      constructor(
        private router: Router,
        private firebaseService: FirebaseService
      ) { }

      canActivate(
        next: ActivatedRouteSnapshot,
        state: RouterStateSnapshot,
      ): Observable<boolean> {

        return this.firebaseService.categoryDone.asObservable().pipe(
          map(Boolean),
          tap(b => if (!b) this.router.navigate(['tabs/tab-profile'] ),
        );
     }
于 2019-11-16T19:05:52.843 回答