角度火身份验证无法在页面刷新后从商店获取用户数据



我使用Firebase身份验证,电子邮件和密码注册。
我的登录函数正在工作,我调用:

await setPersistence(this.auth, browserLocalPersistence);

登录后,查看它是否有效。我在创建新用户后将用户数据保存到firestore,这也可以工作。

我的问题是:

在我的auth.service.ts中,我试图基于auth.currentUser获取用户文档,我在devtools中检查了它,持久性工作正常,当我需要时,我总是从firebase获得currentUser。

我这样写:

this.auth.onAuthStateChanged(user => {
console.log('FIRE AUTH ON AUTH STATE CHANGED RUNNING', user);
if (user) {
this.user$ = of(user).pipe(
switchMap(async user => {
try {
const res = await getDoc(doc(this.db, 'users', user.uid));
console.log(res.data());
return res.data() as FireUser;
} catch (error) {
console.error(error);
return null;
}
})
);
} else {
this.user$ = of(null);
}
});  

登录后,它的工作,但在我做刷新(我仍然得到currentUser正确),函数只是停止,没有任何错误,或任何东西。它只是不会进入switchMap。

我正在记录currentUser在onauthstatechange的开始,我得到它的值正确。.

(也试过这样):

onAuthStateChanged(this.auth, user => {
console.error('USER IS', user);
if (user) {
this.user$ = docData(
doc(this.db, 'users', user.uid)
) as Observable<FireUser>;
} else {
this.user$ = of(null);
}
});

TS: 在组件中显示用户$ Observable数据:
user$ = this.fireAuthService.user$;  

HTML:

<div *ngIf="user$ | async as user">
<pre>
{{ user | json }}
</pre>
</div>

我做错了什么?

所以我的解决方案是(基于@Werner7的答案):

private userSubject$ = new BehaviorSubject<FireUser>(null);
get user$(): Observable<FireUser> {
return this.userSubject$.asObservable();
}
onAuthStateChanged(this.auth, async user => {
console.error('USER IS', user);
if (user) {
this.userSubject$.next(
(await getDoc(doc(this.db, 'users', user.uid))).data() as FireUser
);
} else {
this.userSubject$.next(null);
}
});

这就是我使用的行为主题,我喜欢它,因为它更动态。

export class AuthService {
private readonly user$ = new BehaviorSubject<UserModel | null>(null);
private _internalUserTmp: UserModel;
public get internalUserTemp(): UserModel {
return this._internalUserTmp;
}
private set internalUserTemp(value: UserModel) {
this._internalUserTmp = value;
}
get currentUser(): Observable<UserModel | null> {
return this.user$.asObservable();
}
constructor(
private readonly auth: Auth,
private readonly firestore: Firestore,
private readonly functions: Functions) {
onAuthStateChanged(this.auth, user => {
// console.log("State Chaned: ", user);
this.retrieveUserData(user);
auth.currentUser?.getIdTokenResult().then(idTokenResult => {
// console.log(idTokenResult);
if (!!idTokenResult.claims.superAdmin) {
this._isSuperAdmin$.next(true);
this._isAdmin$.next(true);
} else if(!!idTokenResult.claims.admin){
this._isAdmin$.next(true);
this._isSuperAdmin$.next(false);
}else {
this._isAdmin$.next(false);
this._isSuperAdmin$.next(false);
}
})
});
this.user$.subscribe(user => {
this.internalUserTemp = user as UserModel;
});
}
private async retrieveUserData(user: User | null): Promise<void> {
if (!user) {
this.user$.next(null);
return;
}
if (user.email === undefined || null || '') {
this.user$.next(null);
return;
}
await this.getUserDataByEmail(user.email ? user.email : '').subscribe(
userData => {
this.user$.next(userData);
}
);
}
getUserDataByEmail(email: string) {
return docData(doc(this.firestore, "users/", email));
}

然后我使用UserModel,它的结构是这样的…

export class UserModel extends BaseModel {
uid?: string | null;
auth_id?: string | null;
adminReview?: boolean | null;
//...
constructor(config?: UserModel) {
super();
config = Object.assign({}, config);
this.uid = config.uid;
this.auth_id = config.auth_id;
this.adminReview = config.adminReview;
//...
}