Angular 当身份验证状态更改时,在map操作符内调用一个方法
我正在用Angular 8和Angular 8开发一个web应用程序 我正在尝试实现Firebase身份验证以登录用户,然后在Firestore中读取其数据。最后,使用本地Angular 当身份验证状态更改时,在map操作符内调用一个方法,angular,angularfire2,Angular,Angularfire2,我正在用Angular 8和Angular 8开发一个web应用程序 我正在尝试实现Firebase身份验证以登录用户,然后在Firestore中读取其数据。最后,使用本地BehaviorSubject保存此数据 import {User} from 'firebase'; export interface FirebaseUser { readonly uid: string; readonly email: string; readonly emailVerified: boo
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);
}
}
从“firebase”导入{User};
导出接口FirebaseUser{
只读uid:string;
只读电子邮件:字符串;
只读电子邮件验证:布尔;
}
导出接口IUser{
id?:字符串;
电子邮件:字符串;
名称:字符串;
性别:弦;
}
@可注射()
导出类身份验证服务{
//从Firebase身份验证获取用户的身份验证数据。
private bsCurrentUserAuth:BehaviorSubject=新的BehaviorSubject(null);
readonly currentUserAuth$:Observable=this.bsCurrentUserAuth.asObservable();
//获取用户的文档数据。
private bsCurrentUser:BehaviorSubject=新的BehaviorSubject(null);
只读currentUser$:Observable=this.bsCurrentUser.asObservable();
私有用户$:可观察;
建造师(
私人afAuth:AngularFireAuth,
私人afs:AngularFirestore,
) {
//订阅身份验证状态,然后获取firestore用户文档| | null
this.user$=this.afAuth.authState.pipe(
开关映射(用户=>{
//登录
如果(用户){
返回此.afs.doc(`${COLLECTIONS.USERS}/${user.uid}`)。快照更改()
.烟斗(
映射(更改=>{
const data=将.payload.data()更改为IUser;
const id=changes.payload.id;
const docData={id,…data};
this.saveUser(user,docData);//未调用此函数。
返回文档数据;
}));
}否则{
//注销
这个;
返回(空);
}
})
);
}
//这是没有被称为。
私有存储用户(用户:用户,用户文档:IUser){
log('saveUser');
this.bsCurrentUserAuth.next(用户);
this.bsCurrentUser.next(userDoc);
}
私有clearAll(){
this.bsCurrentUserAuth.next(null);
this.bsCurrentUser.next(空);
}
登录(电子邮件:string,密码:string):承诺{
使用email和password(电子邮件,密码)返回此.afAuth.auth.Signin;
}
}
现在,用户可以登录,但是我想保存在行为子对象中的数据不在那里,因为出于某种原因,saveUser()
方法没有被调用
这个想法是:
登录
在BehaviorSubject
中保存来自Firebase身份验证的用户身份验证数据
将用户的文档数据保存在行为主题中
我的目标是在两个行为主题中提供这些数据,我看不出您实际订阅用户$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);
}
})
);
}
// 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);
}
}
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);
}
}
从“firebase”导入{User};
导出接口FirebaseUser{
只读uid:string;
只读电子邮件:字符串;
只读电子邮件验证:布尔;
}
导出接口IUser{
id?:字符串;
电子邮件:字符串;
名称:字符串;
性别:弦;
}
@可注射()
导出类身份验证服务{
//从Firebase身份验证获取用户的身份验证数据。
private bsCurrentUserAuth:BehaviorSubject=新的BehaviorSubject(null);
readonly currentUserAuth$:Observable=this.bsCurrentUserAuth.asObservable();
//获取用户的文档数据。
private bsCurrentUser:BehaviorSubject=新的BehaviorSubject(null);
只读currentUser$:Observable=this.bsCurrentUser.asObservable();
私有用户$:可观察;
建造师(
私人afAuth:AngularFireAuth,
私人afs:AngularFirestore,
) {
//订阅身份验证状态,然后获取firestore用户文档| | null
this.user$=this.afAuth.authState.pipe(
开关映射(用户=>{
//登录
如果(用户){
返回此.afs.doc(`${COLLECTIONS.USERS}/${user.uid}`)。快照更改()
.烟斗(
映射(更改=>{
const data=将.payload.data()更改为IUser;
const id=changes.payload.id;
const docData={id,…data};
this.saveUser(user,docData);//未调用此函数。
返回文档数据;
}));
}否则{
//注销
这个;
返回(空);
}
})
).subscribe();
//您需要实际订阅用户状态。如果不是单例服务,请确保在用户状态被破坏时也取消订阅
}
//这是没有被称为。
私有存储用户(用户:用户,用户文档:IUser){
log('saveUser');
this.bsCurrentUserAuth.next(用户);
this.bsCurrentUser.next(userDoc);
}
私有clearAll(){
this.bsCurrentUserAuth.next(null);
this.bsCurrentUser.next(空);
}
登录(电子邮件:string,密码:string):承诺{
使用email和password(电子邮件,密码)返回此.afAuth.auth.Signin;
}
}
我为什么需要订阅?我认为te文档的读取将通过返回this.afs.doc(…)
完成。如果我不订阅,保存在Observable中的只是文档的引用?我不明白逻辑…在你订阅之前,你所做的就是创建一个可观察的。可以在其他地方订阅。但除非你真的订阅了它,否则它不会执行。这个.afs.doc(…)永远不会发生,因为observable没有任何东西可以观察到它。谢谢你的解释。我注意到我的IDE在中给了我一个错误。user$
说“Type'Subscription'缺少Type'obbservable'中的以下属性:\ isScalar、source、operator、lift,还有6个。”。知道为什么会出现这种错误吗?