【问题标题】:nested subscribe in angular角度嵌套订阅
【发布时间】:2021-07-12 03:56:20
【问题描述】:

这是我的代码..我需要检查 2 个可观察数据 ..它适用于 1 个可观察数据 如何检查另一个可观察数据

import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, CanActivateChild, Router, RouterStateSnapshot, UrlTree } from '@angular/router';
import { Observable } from 'rxjs';
import { filter, map, take } from 'rxjs/operators'
import { AuthenticationService } from '../services/authentication.service';

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate  {

  constructor(private authService: AuthenticationService, private router: Router) {}

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):  Observable<boolean> | Promise<boolean> | boolean
  {
    
    return this.authService.isAuthenticated.pipe(
      filter(val => val !== null), // Filter out initial Behaviour subject value
      take(1), // Otherwise the Observable doesn't complete!
      map(isAuthenticated => {
        if (isAuthenticated) {  

  TRY 1...........Initial code with direct access without observable but it is not working after login it is not navigate ..if i refresh (f5) then this works
     if( state.url !== '/changepassword'   &&  this.authService.getUserValue.changePassword)
               this.router.navigateByUrl('/changepassword');               
                return true;
----------------------------------------------

         // TRY 2 //Added conditional if 
          -----------------------------------------------------------
           ///i need to subscibe another value and if value is true the route to change 
            password else dashboard should load
           this.authService.getUserValueObs().pipe(
            filter(val => val !== null), // Filter out initial Behaviour subject value
            take(1),
            map(user =>{
                if( state.url !== '/changepassword'   &&  user.changePassword)
                    this.router.navigateByUrl('/changepassword'); 
                }
             ));
            ----------------------------------------------------
           return true;   // i need to retun this value after subscibe of inner observble...
        } else {          
          this.router.navigateByUrl('/')
          return false;
        }
      })
    );
  }
}

当前的 AuthGuard 代码工作正常,但如果订阅值到仪表板更改密码页面的 instea 应该加载,我需要添加另一个条件?如何执行多个订阅方法

编辑:

这是我的身份验证服务类 * 方法..

 export class AuthenticationService {
 
   isAuthenticated: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(null);
 
   userSubject$= new  BehaviorSubject<IAuthenticatedUser>(undefined);

  get getUserValue(): any  {
    return this.userSubject$.value;
  }

  getUserValueObs(): Observable<IAuthenticatedUser>  {
    return this.userSubject$.asObservable();
  }

      login(credentials: {userName:string, password:string}): Observable<any> {
            return this.http.post(`${baseUrl}/authenticate-app`, credentials).pipe(
               map((result: any) => result.data),
               switchMap((user: {userId,userName, fullName refreshToken}) => { 
                if(user)
                    return this.storeUserData(user);
                 }
                  
              }), 
              tap(_ => {
                this.isAuthenticated.next(true);
              })
            )

}

当前的问题是登录时我正在为两个行为主题分配值...但是 Ispasswordchange 有时没有获得值..如果我刷新然后值来

【问题讨论】:

  • 调用是顺序的还是并行的?
  • 你介意分享AuthenticationService的代码吗?
  • @PsyGik 我已经添加了我的登录方法......我认为是并行的......但是有些东西
  • 我已经更新了问题

标签: angular typescript


【解决方案1】:

如果你想从一个 observable 切换到另一个 observable 并使用前一个 observable 的值,你可以使用switchMap 运算符:

return this.authService.isAuthenticated.pipe(
  filter((val) => val !== null), // Filter out initial Behaviour subject value
  take(1), // Otherwise the Observable doesn't complete!
  switchMap((isAuthenticated) => {
    if (isAuthenticated) {
      return this.authService.getUserValueObs().pipe(
        filter((val) => val !== null), // Filter out initial Behaviour subject value
        take(1),
        map((user) => {
          if (state.url !== "/changepassword" && user.changePassword)
            return this.router.navigateByUrl("/changepassword");
          return true;
        })
      );
    } else {
      return this.router.navigateByUrl("/");
    }
  })
);

【讨论】:

  • 感谢您的回答...但是当初始页面加载时您的 getUserValueObs 始终为空,如果我刷新然后转到仪表板..如果我注销然后再次登录然后按预期工作。是延迟加载可能会出现问题...请帮助我
  • 如果你能制作一个 CodeSandbox 以最少的重现此问题,我将能够以更好的方式提供帮助