【问题标题】:Observable<string[]> in ngIf directivengIf 指令中的 Observable<string[]>
【发布时间】:2020-06-02 21:32:57
【问题描述】:

我有一个返回用户角色的方法,例如:

  getUserRoles() : Observable<string[]> {
    return this.getToken().pipe(
      map(token => {
        let payload = decode(token);
        return payload["roles"];
      })
    )
  }

我正在尝试在锚中使用它来隐藏/显示基于以下角色的项目:

<a *ngIf="(authService.getUserRoles | async).includes('admin')" routerLink="/admin" clrDropdownItem>Admin</a>

但是,我得到编译器错误:

ERROR in src/app/components/profile/profile.component.html:15:18 - error TS2769: No overload matches this call.
  The last overload gave the following error.
    Argument of type '() => Observable<string[]>' is not assignable to parameter of type 'Promise<unknown>'.
      Type '() => Observable<string[]>' is missing the following properties from type 'Promise<unknown>': then, catch, [Symbol.toStringTag], finally

15       <a *ngIf="(authService.getUserRoles | async).includes('admin')" routerLink="/admin" clrDropdownItem>Admin</a>
                    ~~~~~~~~~~~~~~~~~~~~~~~~~

  src/app/components/profile/profile.component.ts:7:16
    7   templateUrl: './profile.component.html',
                     ~~~~~~~~~~~~~~~~~~~~~~~~~~
    Error occurs in the template of component ProfileComponent.

无法完全弄清楚我做错了什么。我正在使用 Angular 9。

【问题讨论】:

  • authService.getUserRoles()代替authService.getUserRoles
  • @SankalpBhamare 您的建议实际上使编译器错误消失了。但是现在,当我单击具有锚点的按钮时,整个应用程序会冻结(浏览器也会冻结)。控制台上没有错误。我必须结束浏览器的任务。
  • “整个应用程序冻结(浏览器也冻结)” - 这应该是一个新问题。感觉原因和/admin下的路由和组件有关。
  • Kovac 你测试过这个函数吗,在组件体内部,getUserRoles().subscribe((t)=>console.log(t))?
  • 现在我知道了问题所在,每次视图加载时,它都会调用函数并订阅数据,每次组件重新呈现它自己时都会发生这种情况,然后当订阅者返回导致无限循环的数据,最终导致应用程序中断/挂起。

标签: angular angular-ng-if rxjs-observables


【解决方案1】:

啊,我想我明白了!

我曾经遇到过类似的问题,模板中的函数调用也是如此。长话短说,变更检测触发变更检测,或多或少是while (true);

尝试更改此设置

<a *ngIf="(authService.getUserRoles() | async).includes('admin')" ...

变成类似的东西

<a *ngIf="userIsAdmin" ...

在组件的TS部分

userIsAdmin = false;
onDestroy = new Subject();

ngOnInit() {
    this.authService.getUserRoles().pipe(takeUntil(this.onDestroy)).subscribe(/* assign value to this.userIsAdmin here
}

ngOnDestroy() {
    /* To prevent a memory leak */
    this.onDestroy.next(); 
    this.onDestroy.complete();
}

【讨论】:

    【解决方案2】:

    你的方法行不通……

    即使您将代码更改为:authService.getUserRoles() | async 您的代码将不起作用,因为每次检查您的视图时都会运行此函数,并且 您不会从 async 管道中受益,相反。

    这样会更好

    1) 在组件初始化时订阅你的数据(记得在销毁组件之前取消订阅)。

    2) 创建新管道来处理该逻辑。

    3) 使用guards

    4) 使函数同步:

    .ts
        isInRole(role: string): boolean {
            const token = this.getToken();
            const payload = decode(token);
            return payload && payload["roles"] && payload["roles"].includes(role);
        }
    
    .html
    
         <a *ngIf="isInRole('admin')" routerLink="/admin" clrDropdownItem>Admin</a>
    

    【讨论】:

      猜你喜欢
      • 2021-05-15
      • 1970-01-01
      • 2018-04-25
      • 1970-01-01
      • 2017-08-26
      • 1970-01-01
      • 2017-02-11
      • 1970-01-01
      • 2018-12-30
      相关资源
      最近更新 更多