【问题标题】:How to make http post call inside route guard in angular7?如何在angular7中的路由保护内进行http post调用?
【发布时间】:2020-06-09 15:38:06
【问题描述】:

我有一个 Angular 7 应用程序,在其中我有一个呼叫后响应,并且基于该呼叫后响应,我想让警卫处于活动/非活动状态。我有这样的路线守卫

canActivate = (_router: ActivatedRouteSnapshot): boolean => {
    console.log('in link expiry guard')
    let userEmail = _router.paramMap.get('email');
    let isAllow;

    console.log('params : ', userEmail)
    userEmail = this._utilityService.decryptMsgByCryptoJs(userEmail);
    console.log('user email : ', userEmail)
    this._dataService.post(this._const.userResetPasswordLinkExpiry, { email: userEmail }).subscribe(resp => {
        console.log('verify response : ',resp)
        if (resp.success) {
            console.log('in success')
            isAllow = true;
        } else {
            isAllow = false;
        }
    })
    console.log('allow flag  : ',isAllow)
    if (isAllow) {
        console.log('in allow')
        return true;
    } else {
        console.log('in not allow')
        this._utilityService.navigate('/login');
        this._dataService.exhangeResetPasswordObsMsg({ event: 'linkExpired' });
        return false;
    }
}

但问题是,当我的 http post 通话正在进行时,我的警卫完全执行并返回 false,之后响应来自 post call。我该如何管理这种情况,所以我将根据 http post 呼叫响应使路由为真或假。

【问题讨论】:

  • 问题是您在并发函数之外返回并且代码不断评估。在 post 调用内部而不是外部返回,并返回 PromiseObservable 而不是布尔值。 CanActivate 可以返回其中任何一个 -> angular.io/api/router/CanActivate
  • 你能告诉我答案吗?
  • 查看我更新的问题我已经更新了我的路由守卫。但是现在它在canActivate = (_router: ActivatedRouteSnapshot): Observable<boolean> 线上给出了一个错误。这么说function must return a value
  • 您好,您可以在 gurad 中使用 route reolsver 而不是 http。
  • 您仍然需要整体回电,请参阅:stackoverflow.com/questions/37948068/…\

标签: angular typescript angular-route-guards


【解决方案1】:

如果您想在 canActivate 函数中发出 Http 请求,则需要返回 Observable<boolean> 而不是 boolean,因为您现在正在执行异步操作。

既然你想在失败时导航,你应该返回Observable<boolean | UrlTree>

简单版

constructor(private router: Router) { }

canActivate(route: ActivatedRouteSnapshot, 
    state: RouterStateSnapshot): Observable<boolean | UrlTree> {
  return this.http.post(url, body).pipe(
    map((resp: any) => resp.success ? true : this.router.parseUrl('/path'))
  );   
}

我们正在返回可观察的 http 请求(路由器将通过订阅来调用它),并将响应映射到任一

  • true - 路由器可能会继续到受保护的路由
  • UrlTree - 路由器应该导航到我们返回的路由

应用于您的示例

如果我们将此应用于您的示例,我们需要在管道中做更多的工作,因为您有一个额外的服务调用。

// TODO: inject other services
constructor(private router: Router) { }

canActivate(route: ActivatedRouteSnapshot, 
      state: RouterStateSnapshot): Observable<boolean | UrlTree> {
    const userEmail = route.paramMap.get('email');

    // I am assuming this is a synchronous call
    userEmail = this._utilityService.decryptMsgByCryptoJs(userEmail);

    const url = this._const.userResetPasswordLinkExpiry;
    const body = { email: userEmail };

    return this._dataService.post(url, body).pipe(
      // initial map from response to true/false
      map((resp: any) => resp.success),

      // perform an action if false
      tap(success => {
        if (!success) {
          // I'm assuming this is synchronous. If not, you will need to do a switchMap
          this._dataService.exhangeResetPasswordObsMsg({ event: 'linkExpired' });
        }
      }),
      // final map to boolean | UrlTree
      map(success => success ? true : this.router.parseUrl('/login'))
    );   
}

我假设那里有一些服务调用是同步的。此答案演示了如何在 canActivate 内执行异步调用,并允许路由器导航或返回要导航到的替代路由。

【讨论】:

  • 现在出现这样的错误Cannot find name 'UrlTree'.
  • 我没有把 all 的导入文件放在那里。如果您使用的是 VS Code,您应该能够自动导入它。如果没有,你可以从'@angular/router'手动导入
  • 我已经完成了所有的导入,但之后就发生了。请看这个ibb.co/tB3htqy
  • 错误出现在canActivate。您仍在尝试通过编写canActivate = () 为其分配功能。你只需要把它写成普通的类函数canActivate(/. params ./),就像我的回答一样。
  • 查看我更新的问题。我已根据您的回答更新了我的警卫定义,但仍然出现相同的错误。
猜你喜欢
  • 2019-05-01
  • 2017-03-10
  • 1970-01-01
  • 1970-01-01
  • 2011-08-30
  • 1970-01-01
  • 2016-05-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多