模板渲染中authState可观察到的延迟的模板中的Angularfire条件逻辑

时间:2019-04-14 11:02:50

标签: angular firebase authentication rxjs angular2-observables

嗨,我正在用@ angular / fire构建一个角度应用程序。在auth服务中,我有一个用户可观察的用户,如果该用户已通过身份验证,则获取当前用户的值;如果该用户未通过身份验证,则获取null的值。

export class AuthService {
 user$: Observable<User>;

  constructor(private afAuth: AngularFireAuth, private afs: 
 AngularFirestore) {
    this.user$ = this.afAuth.authState.pipe(
      switchMap(user => {
        if (user) {
          return this.afs.doc<User>(`users/${user.uid}`).valueChanges();
        } else {
          return of(null);
        }
      })
    )
  }

它在服务的构造函数中,因此所有注入服务的组件都可以看到user $变量。现在,我有一个导航,它根据用户是否通过身份验证显示不同的按钮。

<ul>

  <!-- user IS NOT logged in -->
  <li *ngIf="!(authService.user$ | async)">
    This is visible if user is NOT logged in
  </li>

  <!-- user IS logged in -->
  <li *ngIf="authService.user$ | async" fxHide.xs>
    This is visible if user IS logged in
  </li>
</ul>

observable用户$在开始时为空,并且需要一些时间取值,这意味着即使用户已登录,模板中的“如果用户未登录也可见”。将在可观察对象获取当前用户的值之前渲染几秒钟,然后切换到另一个li标签。有没有更好的方法来检查经过身份验证的用户以防止这种情况?注意我不能使用路由保护,因为我不想阻塞整个页面,而只能阻塞按钮和某些其他元素之间的某些条件逻辑。这是与此重复的问题:Angular 6 AngularFireAuth check if user is logged in before page rendered,但我没有找到答案。 预先感谢

1 个答案:

答案 0 :(得分:1)

在auth服务中,添加一个主题,组件可以订阅该主题并等待某些响应

import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs';
@Injectable()
export class AuthService {

  userAccessSubject = new Subject();

  user$: Observable<User>;

  constructor(private afAuth: AngularFireAuth, private afs:
    AngularFirestore) {
    this.afAuth.authState.pipe(
      switchMap(user => {
        if (user) {
          this.userAccessSubject.next(this.afs.doc<User>(`users/${user.uid}`).valueChanges());
        } else {
          this.userAccessSubject.next(null);
        }
      })
    )
  }

  getUserAccess() {
    return this.userAccessSubject.asObservable();
  }
}

然后在组件中,从订阅块获取userAccess

constructor() {
  // Here add code to enable loader
  this.authService.getUserAccess()
    .subscribe(userAccessResponse => {
      this.userAccess = userAccessResponse;
      // Hide loader
    })
}