ngIf 指令中的 Observable<string[]>

Observable<string[]> in ngIf directive

我有一个方法 returns 用户的角色如下:

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

我正在尝试将其用于 hide/show 基于以下角色的项目的锚点:

<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.

啊,我想我明白了!

我曾经遇到过类似的问题,同样是模板中的函数调用。长话短说,change detection触发了change detection,差不多就是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();
}

你的方法行不通...

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

会更好

1) Subscribe to your data in the initilazition of the component (remember to unsubscribe before you destroy the component).

2) Create new pipe to handle that logic.

3) Use guards.

4) Make the function synchronous:

.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>