当 auth 状态改变时调用 map 运算符内部的方法

call a method inside of the map operator when the auth state changes

我正在 Angular 8 和 Angularfire 中开发 Web 应用程序。

我正在尝试实施 Firebase 身份验证以登录用户,然后在 Firestore 中读取其数据。最后,使用本地 BehaviorSubject.

保存此数据
import {User} from 'firebase';

export interface FirebaseUser {
  readonly uid: string;
  readonly email: string;
  readonly emailVerified: boolean;
}

export interface IUser {
  id?: string;
  email: string;
  name: string;
  gender: string;
}

@Injectable()
export class AuthService {

  // To have the user's auth data from Firebase Authentication.
  private bsCurrentUserAuth: BehaviorSubject<FirebaseUser> = new BehaviorSubject<FirebaseUser>(null);
  readonly currentUserAuth$: Observable<FirebaseUser> = this.bsCurrentUserAuth.asObservable();

  // To have the user's document data.
  private bsCurrentUser: BehaviorSubject<IUser> = new BehaviorSubject<IUser>(null);
  readonly currentUser$: Observable<IUser> = this.bsCurrentUser.asObservable();

  private user$: Observable<IUser>;

  constructor(
    private afAuth: AngularFireAuth,
    private afs: AngularFirestore,
  ) {
    // Subscribe to the auth state, then get firestore user document || null
    this.user$ = this.afAuth.authState.pipe(
      switchMap(user => {
        // Logged in
        if (user) {
          return this.afs.doc<IUser>(`${COLLECTIONS.USERS}/${user.uid}`).snapshotChanges()
            .pipe(
              map(changes => {
                const data = changes.payload.data() as IUser;
                const id = changes.payload.id;
                const docData = {id, ...data};
                this.saveUser(user, docData); // This is not being called.
                return docData;
              }));
        } else {
          // Logged out
          this.clearAll();
          return of(null);
        }
      })
    );
  }

  // This is not being called.
  private saveUser(user: User, userDoc: IUser) {
    console.log('saveUser');
    this.bsCurrentUserAuth.next(user);
    this.bsCurrentUser.next(userDoc);
  }

  private clearAll() {
    this.bsCurrentUserAuth.next(null);
    this.bsCurrentUser.next(null);
  }

  login(email: string, password: string): Promise<UserCredential> {
    return this.afAuth.auth.signInWithEmailAndPassword(email, password);
  }

}

现在,用户可以登录,但是,我想保存在 BehaviorSubject 中的数据不存在,因为由于某种原因,saveUser() 方法没有被调用。

想法是:

  1. 登录
  2. 将来自 Firebase 身份验证的用户身份验证数据保存在 BehaviorSubject
  3. 将用户文档数据保存在BehaviorSubject.

我的目标是让这些数据在两个 BehaviorSubject.

中可用

我没有看到您实际上在哪里订阅了 user$ observable。看看这个,假设您有正确的导入并订阅 user$,它应该可以正常工作。登录和获取用户状态没有耦合,所以我猜你只是缺少订阅位。

import {User} from 'firebase';

export interface FirebaseUser {
  readonly uid: string;
  readonly email: string;
  readonly emailVerified: boolean;
}

export interface IUser {
  id?: string;
  email: string;
  name: string;
  gender: string;
}

@Injectable()
export class AuthService {

  // To have the user's auth data from Firebase Authentication.
  private bsCurrentUserAuth: BehaviorSubject<FirebaseUser> = new BehaviorSubject<FirebaseUser>(null);
  readonly currentUserAuth$: Observable<FirebaseUser> = this.bsCurrentUserAuth.asObservable();

  // To have the user's document data.
  private bsCurrentUser: BehaviorSubject<IUser> = new BehaviorSubject<IUser>(null);
  readonly currentUser$: Observable<IUser> = this.bsCurrentUser.asObservable();

  private user$: Observable<IUser>;

  constructor(
    private afAuth: AngularFireAuth,
    private afs: AngularFirestore,
  ) {
    // Subscribe to the auth state, then get firestore user document || null
    this.user$ = this.afAuth.authState.pipe(
      switchMap(user => {
        // Logged in
        if (user) {
          return this.afs.doc<IUser>(`${COLLECTIONS.USERS}/${user.uid}`).snapshotChanges()
            .pipe(
              map(changes => {
                const data = changes.payload.data() as IUser;
                const id = changes.payload.id;
                const docData = {id, ...data};
                this.saveUser(user, docData); // This is not being called.
                return docData;
              }));
        } else {
          // Logged out
          this.clearAll();
          return of(null);
        }
      })
    ).subscribe();
//you need to actually subscribe to the user state be sure to also unsubscribe when this is destroyed if not a singleton service
  }

  // This is not being called.
  private saveUser(user: User, userDoc: IUser) {
    console.log('saveUser');
    this.bsCurrentUserAuth.next(user);
    this.bsCurrentUser.next(userDoc);
  }

  private clearAll() {
    this.bsCurrentUserAuth.next(null);
    this.bsCurrentUser.next(null);
  }

  login(email: string, password: string): Promise<UserCredential> {
    return this.afAuth.auth.signInWithEmailAndPassword(email, password);
  }

}