【问题标题】:Display enum string initializer instead of the enum value显示枚举字符串初始值设定项而不是枚举值
【发布时间】:2021-07-27 19:51:30
【问题描述】:

标题很容易解释。 get role(): string 不返回字符串初始值设定项。例如。它返回“管理员”,而不是“主管管理员”。 Role["Administrator"] 会这样做,但 IUser.role 实际上是 Role | undefined,这是问题所在,我不能简单地这样做

get role(): string {
  return Role[this.authService.userInfo?.role];
}

因为这个。

header.component.ts

import { Component } from '@angular/core';

import { AuthService } from '@core/services';
import { LayoutComponent } from '../layout.component';

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html'
})
export class HeaderComponent {
  get username(): string {
    return this.authService.userInfo?.username || '';
  }

  get role(): string {
    return this.authService.userInfo?.role || '';
  }

  constructor(private authService: AuthService, public app: LayoutComponent) {}

  signOut(event: any) {
    this.authService.signOut();

    event.preventDefault();
  }
}

user.model.ts

export interface IUser extends IEntity {
  email: string;
  username: string;
  role: Role;
}

export enum Role {
  Administrator = 'Head Administrator',
  DepartmentAdministrator = 'Department Administrator',
  User = 'Super User'
}

auth.service.ts

import { Injectable, OnDestroy } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Router } from '@angular/router';

import { BehaviorSubject, Observable, of, Subscription } from 'rxjs';
import { delay, map, tap } from 'rxjs/operators';

import { environment } from '@env';
import { IAuthResponse, IUser } from '@core/models';
import { INITIAL_AUTH_STATE } from '@core/constants';

import { JwtService } from '../util';

@Injectable({
  providedIn: 'root'
})
export class AuthService implements OnDestroy {
  private readonly TOKEN_URL = `${environment.apiUrl}/Accounts/token`;

  private currentUserSubject = new BehaviorSubject<IAuthResponse>(INITIAL_AUTH_STATE);
  private timer!: Subscription;

  currentUser$: Observable<IAuthResponse> = this.currentUserSubject.asObservable();

  get userInfo(): IUser | null {
    const accessToken = this.currentUserValue?.accessToken;

    return accessToken ? this.jwtService.decodeToken<IUser>(accessToken) : null;
  }

  private get currentUserValue(): IAuthResponse | null {
    return this.currentUserSubject.value;
  }

  private get localStorageCurrentUser(): IAuthResponse {
    const localStorageUser = localStorage.getItem('currentUser');
    return localStorageUser ? JSON.parse(localStorageUser) : INITIAL_AUTH_STATE;
  }

  constructor(
    private httpClient: HttpClient,
    private router: Router,
    private jwtService: JwtService
  ) {
    this.currentUserSubject.next(this.localStorageCurrentUser);
    window.addEventListener('storage', this.storageEventListener.bind(this));
  }

  ngOnDestroy(): void {
    window.removeEventListener('storage', this.storageEventListener.bind(this));
  }

  signIn(username: string, password: string): Observable<IAuthResponse> {
    const TOKEN_URL: string = this.TOKEN_URL + '/create';

    return this.httpClient
      .post<IAuthResponse>(TOKEN_URL, {
        username,
        password
      })
      .pipe(
        map((res) => {
          if (res && res.accessToken) {
            this.setCurrentUser(res);
          }

          return res;
        })
      );
  }

  signOut(): void {
    this.clearCurrentUser();
    this.router.navigate(['auth']);
  }

  refreshToken(): Observable<IAuthResponse | null> {
    const refreshToken = this.currentUserValue?.refreshToken;
    if (!refreshToken) {
      this.clearCurrentUser();
      return of(null);
    }

    return this.httpClient.post<IAuthResponse>(`${this.TOKEN_URL}/refresh`, { refreshToken }).pipe(
      map((res) => {
        this.setCurrentUser(res);
        return res;
      })
    );
  }

  private setCurrentUser(user: IAuthResponse): void {
    this.currentUserSubject.next(user);
    this.setLocalStorage(user);
    this.startTokenTimer();
  }

  private clearCurrentUser(): void {
    this.currentUserSubject.next(INITIAL_AUTH_STATE);
    this.clearLocalStorage();
    this.stopTokenTimer();
  }

  private setLocalStorage(userState: IAuthResponse): void {
    localStorage.setItem('currentUser', JSON.stringify(userState));
    localStorage.setItem('login-event', 'login' + Math.random());
  }

  private clearLocalStorage(): void {
    localStorage.removeItem('currentUser');
    localStorage.setItem('logout-event', 'logout' + Math.random());
  }

  private getTokenRemainingTime(): number {
    const expiresAtUtc = this.currentUserValue?.expiresAtUtc;
    if (!expiresAtUtc) {
      return 0;
    }
    const expires = new Date(expiresAtUtc);
    return expires.getTime() - Date.now();
  }

  private startTokenTimer(): void {
    const timeout = this.getTokenRemainingTime();
    this.timer = of(true)
      .pipe(
        delay(timeout),
        tap(() => this.refreshToken().subscribe())
      )
      .subscribe();
  }

  private stopTokenTimer(): void {
    this.timer?.unsubscribe();
  }

  private storageEventListener(event: StorageEvent): void {
    if (event.storageArea === localStorage) {
      if (event.key === 'logout-event') {
        this.currentUserSubject.next(INITIAL_AUTH_STATE);
      }

      if (event.key === 'login-event') {
        location.reload();
      }
    }
  }
}

【问题讨论】:

    标签: typescript angular12


    【解决方案1】:

    你写的代码是正确的。

    我在一个孤立的操场上进行了实验,并创建了 2 个函数:第一个返回字符串初始值设定项,第二个返回枚举值名称。

    enum Role {
      Administrator = 'Head Administrator',
      DepartmentAdministrator = 'Department Administrator',
      User = 'Super User'
    }
    
    function getRoleName1(role: Role): string {
        return role
    }
    
    function getRoleName2(role: Role) {
        const roleEnum = Role as Record<string, string>
        for (const key of Object.keys(roleEnum)) {
            if (roleEnum[key] === role) {
                return key
            }
        }
    
        return undefined
    }
    
    console.log('1:', getRoleName1(Role.Administrator)) // Head Administrator
    console.log('2:', getRoleName2(Role.Administrator)) // Administrator
    

    第一个函数正在做你需要的事情,我看到在你的代码中你用类似的方式编写了它。

    我怀疑它没有按预期工作,因为枚举与您的后端实际返回的不匹配,即它可能返回“管理员”而不是“主管管理员”。

    【讨论】:

    • console.log(role = ${this.authService.userInfo?.role});role = Administrator,这就是它返回的内容。这是来自 JWT 令牌:"role": "Administrator",。所以它基本上应该可以工作,但它没有。
    • @nop,那么您需要更改您的枚举声明。基本上,你需要交换等号的左右部分
    • 但我需要在中间显示那个空间
    • @nop 'Head Administrator' = 'Administrator'
    • 好的,我只是让后端返回一个字符串。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 2017-03-16
    • 1970-01-01
    • 1970-01-01
    • 2023-01-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多