繁体   English   中英

结合Angular中的RxJS Observable

[英]Combine RxJS Observable in Angular

问题 :如果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”

我会使用路由守卫来做您正在描述的事情:

这是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']);
            }
        })
    }
}

我不是100%知道您在做什么,但这听起来好像combineLatest可能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.urlBehaviorSubject一个可观察对象,因此在您订阅时它将为您提供最新结果,并且我认为Firebase Auth服务也是如此,但是您必须对其进行测试

可能会有语法错误,只需直接输入即可,但这是您的基本combineLatest

最后,我得到了@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"]);
    }
  }
);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM