AngularFireAuth在路由更改时清除用户状态
在我对可观察物、AngularFireAuth和firebase身份验证的理解中,我似乎遇到了困难。下面是我的身份验证服务的一个片段AngularFireAuth在路由更改时清除用户状态,angular,authentication,observable,Angular,Authentication,Observable,在我对可观察物、AngularFireAuth和firebase身份验证的理解中,我似乎遇到了困难。下面是我的身份验证服务的一个片段 export class AuthService { user$: Observable<firebase.User>; constructor( private db: AngularFirestore, private fireAuth: AngularFireAuth, ) { this.us
export class AuthService {
user$: Observable<firebase.User>;
constructor(
private db: AngularFirestore,
private fireAuth: AngularFireAuth,
) {
this.user$ = fireAuth.authState.pipe(
switchMap(user => {
if (user) {
return this.db.doc<User>(`users/${user.uid}`).valueChanges();
} else {
return of(null);
};
})
);
}
我尝试在authService和组件中创建方法来检索和提取数据,要么在第一页加载时有效,要么仅在从路由更改返回时有效
我确实尝试过将auth服务中的代码更改为change take(1),这使得订单可以正常工作。路由更改后和登录时。但是,标头组件停止工作,用户信息在登录时不会更改
user$: Observable<firebase.User>;
constructor(
private db: AngularFirestore,
private fireAuth: AngularFireAuth,
) {
this.user$ = fireAuth.authState.pipe(
take(1),
switchMap(user => {
if (user) {
return this.db.doc<User>(`users/${user.uid}`).valueChanges();
} else {
return of(null);
};
})
);
user$:可观察;
建造师(
私人数据库:AngularFirestore,
私人消防员:AngularFireAuth,
) {
this.user$=fireAuth.authState.pipe(
以(1)为例,
开关映射(用户=>{
如果(用户){
返回这个.db.doc(`users/${user.uid}`)。valueChanges();
}否则{
返回(空);
};
})
);
除此之外,您的代码片段看起来非常完美
您在两个组件中使用user$
订阅:页眉和签出。页眉组件在所有情况下都可以正常工作,因为无论您的路线如何,该组件始终位于页面顶部(我根据您的问题假设)。但只有当您导航到该页面时,才会显示签出组件。有趣的是,user$
obseravble会在用户登录时立即发送用户的详细信息,而在此期间,签出组件甚至不会显示,因此不会创建该组件,也不会显示订阅了user$
observable。user$
在创建签出组件并订阅它时不会重播最后一个值。因此,您在此处看不到登录用户的详细信息
因此,您必须使用来捕获已登录用户的详细信息。这里使用ReplaySubject的主要原因是它可以将一些旧的发出值重放到新订户。下面让我们看看如何做到这一点
AuthService
// ...
import { ReplaySubject } from 'rxjs';
// ...
export class AuthService {
// Create a ReplaySubject to store the history of logged in users
private loggedInUsersSubject = new ReplaySubject<firebase.User>(1);
// user$ is now returns an obseravble for the history subject
get user$(): Observable<firebase.User> {
return this.loggedInUsersSubject.asObservable();
}
constructor(
private db: AngularFirestore,
private fireAuth: AngularFireAuth,
) {
// do not store the fireAuth observable in user$
// Instead push new logged in users to the ReplaySubject
fireAuth.authState.pipe(
switchMap(user => {
if (user) {
return this.db.doc<User>(`users/${user.uid}`).valueChanges();
} else {
return of(null);
};
})
).subscribe(user => {
// console.log(user);
// Push the details of logged in user to ReplaySubject
this.loggedInUsersSubject.next(user);
});
}
/。。。
从“rxjs”导入{ReplaySubject};
// ...
导出类身份验证服务{
//创建ReplaySubject以存储登录用户的历史记录
private loggedInUsersSubject=新的ReplaySubject(1);
//用户$is现在返回历史主题的obseravble
获取用户$():可观察{
返回此.loggedinUsersObject.asObservable();
}
建造师(
私人数据库:AngularFirestore,
私人消防员:AngularFireAuth,
) {
//不要将fireAuth可见存储在用户中$
//而是将新登录的用户推送到ReplaySubject
fireAuth.authState.pipe(
开关映射(用户=>{
如果(用户){
返回这个.db.doc(`users/${user.uid}`)。valueChanges();
}否则{
返回(空);
};
})
).subscribe(用户=>{
//console.log(用户);
//将登录用户的详细信息推送到ReplaySubject
this.loggedinUsersObject.next(用户);
});
}
如上面的代码片段所示,我们正在使用缓冲区大小为1的Replay主题,以便它可以存储最后发出的值。现在,任何新订阅者都将在订阅时获得最后发出的值
Header组件应该和以前一样工作正常,但是现在Checkouts组件还将捕获登录用户的详细信息,并在代码中不做任何更改的情况下显示它
p.S:
从Checkout组件中删除所有rxjs操作符和您所做的实验,以使上述解决方案正常工作。还可以订阅
ngOnInit()中的user$
observable
方法在签出组件中,而不是在构造函数中。非常感谢。我在这个问题上纠缠了几天。我尝试了replay主题,但我既没有实现缓冲区大小,也没有订阅,而是使用.next()将用户值推送到ReplaySubject。我现在对这个概念有了更好的理解。我感谢您的帮助。
constructor(
public auth: AuthService,
public stripePayment: PaymentService,
private cart: CartService
) {
//this.auth.user$.subscribe( user => this.userData = user)
}
ngOnInit(){
this.auth.user$.subscribe( data => console.log(data) )
}
user$: Observable<firebase.User>;
constructor(
private db: AngularFirestore,
private fireAuth: AngularFireAuth,
) {
this.user$ = fireAuth.authState.pipe(
take(1),
switchMap(user => {
if (user) {
return this.db.doc<User>(`users/${user.uid}`).valueChanges();
} else {
return of(null);
};
})
);
// ...
import { ReplaySubject } from 'rxjs';
// ...
export class AuthService {
// Create a ReplaySubject to store the history of logged in users
private loggedInUsersSubject = new ReplaySubject<firebase.User>(1);
// user$ is now returns an obseravble for the history subject
get user$(): Observable<firebase.User> {
return this.loggedInUsersSubject.asObservable();
}
constructor(
private db: AngularFirestore,
private fireAuth: AngularFireAuth,
) {
// do not store the fireAuth observable in user$
// Instead push new logged in users to the ReplaySubject
fireAuth.authState.pipe(
switchMap(user => {
if (user) {
return this.db.doc<User>(`users/${user.uid}`).valueChanges();
} else {
return of(null);
};
})
).subscribe(user => {
// console.log(user);
// Push the details of logged in user to ReplaySubject
this.loggedInUsersSubject.next(user);
});
}