【问题标题】:Angular 2 - CanActivate Observable get value after SubscribeAngular 2 - CanActivate Observable 在订阅后获取价值
【发布时间】:2017-05-16 17:23:45
【问题描述】:

如果用户已登录,我会对我的网络服务进行“CanActivate”检查。

“CanActivate”返回 Observable。唯一担心的是,我需要恢复此布尔值的值,以便能够在用户连接与否时调整我的视图,而无需重做第二个请求......

canActivate(): Observable<boolean>|boolean {
    return this.connected();
  }
public connected() : Observable<boolean>{
    return this.http.get(this.connectedUrl,{ withCredentials: true })
      .map(this.extractBoolean)
      .catch(this.handleError);
  }

感谢您的帮助

【问题讨论】:

  • 你保存在用户端的每一个东西都可以被用户编辑。因此,在每个页面视图中,您都应该发送一个新请求。
  • 问题是什么?
  • @DanielCooke 如果我没记错的话,乔丹有一个后卫,他在其中进行 ajax 调用以获取用户。之后加载一个组件并在该组件中进行第二次 ajax 调用以获取用户。问题:如何只需 1 个电话即可完成。

标签: angular guard canactivate


【解决方案1】:

如果您想在后端发出请求以确保用户已连接时保存一些数据,而不是在 guard 中发出 HTTP 请求,而是创建一个执行此请求的 service(即无论如何,这是一个很好的做法,无论您是否要保存请求,都应该这样做)。

也就是说,在你的service 中,这是一个单例,你可以简单地map 你的调用(这会导致一个Observable)并将值保存在你的service 中。

例如:

@Injectable()
export class SomeService {
  private userData: IUserData;

  constructor(private http: Http) { }

  getUserDataIfConnected() {
    this.http.get('http://some-url')
      .map((res: Response) => res.json() as IUserData)
      .map(userData => this.userData = userData)
  }
}

那么请注意:

canActivate(): Observable<boolean> {
  return this.someService.getUserDataIfConnected()
    // if there was no error, we don't care about the result, just return true : The user is connected
    .mapTo(true)
    // if the user wasn't logged, your backend shoud return an HTTP error code in the header
    // and angular HTTP service will throw an error
    .catch(err => return Observable.of(false))
}

不必比这更复杂:)

【讨论】:

    【解决方案2】:

    我有一个类似的问题,并使用身份验证服务解决了它,我改为使用 BehaviorSubject 来跟踪成员身份验证状态:

    public member: Subject<Member> = new Subject<Member>();
    
    private _cachedMember: Member;
    private _member$: BehaviorSubject<Member>;
    
    constructor(private _http: Http, private _router: Router) {         
    }
    
    get member$(): Observable<Member> {     
        if (!this._cachedMember) {          
            this.getAuthorizedMember().subscribe();
        }
        return this._member$.asObservable();
    }
    
    private getAuthorizedMember(): Observable<Member> {
         // call your auth API and set _cachedMember accordingly:
         this._cachedMember = member;
         this._member$.next(this._cachedMember);
    }
    

    我的 auth.guard.ts canActivate 实现:

    canActivate(): Observable<boolean> | boolean {
    
            return this._authService.member$.map(member => {
                if (member) return true;
                else {
                    // Set entry url
                    var currentUrl: URL = new URL(this._document.location.href);
                    this._authService.entryUrl = currentUrl.pathname;
    
                    this._router.navigate(['/']);
                    return false;
                }
            });
    
    }
    

    else语句保存url请求,所以会员登录后重定向正确。

    那么你只需要在 _cachedMember 为空时调用你的认证 API。请记住在注销时将 _cachedMember 设置为 null 并通知主题。

    logout() {
        this._cachedMember = null;
        this._member$.next(this._cachedMember );
    }
    

    [编辑] 我发现早期解决方案存在问题。将授权机制包装在可观察对象中是一个好主意,如果 _member$ 主题已分配,则进行空检查。如果直接导航到被保护的路由,那么初始状态是有效的!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-30
      • 2019-05-05
      • 2016-10-28
      • 2020-04-19
      • 2017-10-18
      • 1970-01-01
      • 2017-03-24
      • 2020-05-12
      相关资源
      最近更新 更多