【问题标题】:How to process data from api response then return a boolean value synchronously in angular?如何处理来自 api 响应的数据,然后以角度同步返回一个布尔值?
【发布时间】:2021-06-09 18:35:38
【问题描述】:

我的服务中有一个简单的功能:

  /**
   * Funtion to check if the user logged in has admin rights
   */
  isAdmin(user_id: string) {
    var adminTemp: boolean;
    this.httpClient
        .get(`${this.urk}/${user_id}`)
        .subscribe((data: any) => {
          if (data.includes('Admin')) {
            adminTemp = true;
          } else {
            adminTemp = false;
          }
        });
    return adminTemp;
  }

此函数在canActivate 函数中调用,该函数需要一个布尔值来确定用户是否为管理员。

canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
    if(this.loginService.isAdmin('123')){
      return true;
    }
    else{
      return this.router.parseUrl("/admin/logout");
    }
  }

问题是在调用 api 之前,它需要一个 undefined 的值并将用户标记为非管理员。我理解这是因为订阅本身是一个异步调用。我找不到任何其他方法来弄清楚如何做到这一点,因为必须先处理 api 响应才能知道他们是否是用户,否则我会使用简单的 return 语句。我应该如何进行?

【问题讨论】:

    标签: angular xmlhttprequest subscribe auth-guard canactivate


    【解决方案1】:

    您的问题是您没有利用响应式编程(这是 Angular 在 Rxjs 的帮助下带来的最大优势之一)。

    在您的函数 isAdmin() 中,它调用异步的 http,您不确定当您返回 adminTemp 时,它已被分配了来自 http 结果的值。

    相反,您不应该从 asAdmin 订阅 http 调用,只需将其作为 observable 返回,并让 canActive 处理它。所以try not to subscribe if you can avoid it,会帮你提高效率。

          isAdmin(user_id: string): Observable<boolean> {
            
            return this.httpClient
                .get(`${this.urk}/${user_id}`)
                .pipe(
                   switchMap((data) => {
                     if (data.includes('Admin')) {
                       return of(true);
                     } else {
                      return of(false);
                     }
                    })
                 );
            
          }
    

    优点是canActive()也可以返回Observable,所以可以很方便的在canActive()中使用,如下:

        canActivate(
            next: ActivatedRouteSnapshot,
            state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
            return this.loginService.isAdmin('123').pipe(
         map((res) => {
          if (res) {
             return true;
          } else {
             return  this.router.parseUrl("/admin/logout");   
          }
         })
     );
    
          }
    

    【讨论】:

    • 非常感谢您的回答。在 canActivate() 代码中,您是否正在检查 if(res) 是否有值?这是用于确保进行 http 调用然后只检查响应的逻辑吗?另外,我检查if (data.includes('Admin')) { 的部分实际上不是直接的,权限所在的还有另一个属性。所以它就像if (data.groups.includes('Admin')) {。但是当我这样做时,我在终端“对象”类型上不存在属性“组”出现错误。有什么想法吗?
    • 你可以尝试在 http 调用 http.get&lt;YourType&gt;(...)987654328@ 时将响应转换为类型
    • 我仍然从 Type 'Observable&lt;boolean&gt;' is not assignable to type 'boolean' 的角度终端收到错误消息。我可以忽略它吗?
    • 我明白了,其实我们这里需要用到switchMap,你的httpClient.get没有返回Observable,所以我们需要用switchMap来转换。我已经更新了答案
    • 在html页面中使用,可以和异步管道一起使用&lt;div *ngIf="loginService.isAdmin('123') | async"&gt; admin can see&lt;/div&gt;
    猜你喜欢
    • 2019-02-23
    • 2013-11-12
    • 1970-01-01
    • 2022-01-09
    • 2021-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多