问题:如果firebase-auth没有用户登录,我需要转到登录页面,如果有用户登录,我需要转到备用页面。
要实现此目的,它将在构造函数服务中调用一个函数。
private isLoginRequired() {
// Firebase auth service observable
let authSub = this.afAuth.authState;
// Current route service observable
let routeSub = this.activatedRoute.url;
//Alternate App Page
//this.router.navigate(["tool/event-management/events"]);
//Login Page
//this.router.navigate(["tool/event-management/login"]);
}
现在,我需要以一种这样的方式来组合这些可观察物:如果其中任何一个的值发生变化,我都可以通过一次订阅来收集这两个可观察物的当前值。
something.subscribe(observableSnapshots => {
let snapshot_auth = observableSnapshots[0];
let snapshot_route = observableSnapshots[1];
if(condition<snapshot_route, snapshot_auth>){
// do anything positive
}
else{
// do anything negative
}
});
我知道可以通过嵌套订阅来实现,但这肯定不是一种有效的方式。
我也尝试过mergeMap但无法达到要求,这是代码段(无效)
routeSub
.pipe(mergeMap(event1 => authSub.pipe(map(event2 => "test"))))
.subscribe(result => {
console.log(result);
});
请告诉我一个更好的出路。预先感谢。
依赖关系:“ rxjs”:“〜6.3.3”
答案 0 :(得分:2)
我会使用路由防护器来执行您所描述的操作:
这是Jeff Delaney的AngularFirebase网站上经过稍微修改的代码段,请参见:https://angularfirebase.com/lessons/google-user-auth-with-firestore-custom-data/:
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
import { AngularFireAuth } from '@angular/fire/auth';
import { Observable } from 'rxjs';
import { tap, map, take } from 'rxjs/operators';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private auth: AngularFireAuth, private router: Router)
{}
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> {
return this.auth.authState.pipe()
take(1),
map(user => !!user),
tap(loggedIn => {
if (!loggedIn) {
console.log('access denied')
this.router.navigate(['/login']);
}
})
)
}
}
以下是将防护添加到路由器的方法:
const routes: Routes = [
{ path: '**', component: SomeComponent, canActivate: [AuthGuard]},
]
您可以按照我在此处所做的操作导入在守卫中可观察到的Firebase auth
,但是,最好在自己的服务imo中添加它。检查指向AngularFirebase的链接,以查看执行此操作的服务的代码。
如果您要在注销后将用户拒之门外,请在组件中尝试以下代码:
export class SomeComponent implements OnInit {
constructor(private auth: AngularFireAuth, private router: Router)
{
ngOnInit(): void {
this.auth.authState.subscribe((authObj) => {
if(authObj === null){
this.router.navigate(['/login']);
}
})
}
}
答案 1 :(得分:1)
我不确定您在做什么,但听起来combineLatest
可能有用
// Firebase auth service observable
let authSub = this.afAuth.authState;
// Current route service observable
let routeSub = this.activatedRoute.url;
const sub = combineLatest(authSub, routeSub)
.pipe(
tap(([authResult, routeResult]) => {
// the above uses array param destructuring, so we have two variables
if(authResult === something and routeResult === something){
//Do Something
}
else {
// do something else
}
})
)
.subscribe();
activatedRoute.url
是observable of a BehaviorSubject
,因此在您订阅时它将为您提供最新的结果,我认为Firebase Auth服务也是如此,但是您必须对其进行测试< / p>
其中可能存在语法错误,只需直接输入即可,但这是您的基本combineLatest
答案 2 :(得分:0)
最后,我在@Drenai帮助下找到了此代码段。
private isLoginRequired():void {
let authSub: Observable<firebase.User> = this.afAuth.authState;
let routeSub: Observable<any> = this.router.events;
combineLatest(authSub, routeSub).subscribe(
([authSubSnap, routeSubSnap]):void => {
let islogin: boolean = !!authSubSnap;
let current_url: string = routeSubSnap.url;
if (!islogin) {
this.router.navigate([this.loginPageURL]);
} else if (current_url === this.loginPageURL && islogin) {
this.router.navigate(["tool/event-management/events"]);
}
}
);
}