簡體   English   中英

在這種情況下,是否有更好的 RXJs 運算符可以使用?

[英]Is there a better RXJs Operator to use in this scenario?

我有一個服務方法,它執行以下操作:

  1. 通過 ID 從數據庫中查找用戶
  2. 檢查是否找到了用戶
  3. 使用 bcrypt 將存儲在數據庫中的密碼與作為參數提供的密碼進行比較
  4. 如果密碼不正確,則拋出 UnauthorizedException,如果正確則返回用戶。

我只是想知道是否有更好的方法使用 RxJS 運算符來執行此操作,因為我不喜歡從 bcrypt.compare 中獲得 pipe:

public validateUser(email: string, pass: string): Promise<UserDto> {
    return this.userService
      .findOne({ email })
      .pipe(
        map((user: UserDto) => {
          if (!user || !user.password) {
            return throwError(new UnauthorizedException());
          }
          return user;
        }),
        switchMap((user: UserDto) => {
          return from(
            bcrypt.compare(pass, user.password) as Promise<boolean>
          ).pipe(
            map((passwordIsCorrect) => ({
              passwordIsCorrect,
              user
            }))
          );
        }),
        switchMap((res) => {
          if (!res.passwordIsCorrect) {
            return throwError(new UnauthorizedException());
          }
          return of(res.user);
        })
      )
      .toPromise();
  }

我認為沒有更好的運算符可以使用,但是您可以將代碼簡化為全部在同一個switchMap中,如下所示:

  public validateUser(email: string, pass: string): Promise<UserDto> {
    return this.userService.findOne({ email }).pipe(
      switchMap(user => {
        if (!user?.password) {
          return throwError(new UnauthorizedException());
        }

        return from(bcrypt.compare(pass, user.password)).pipe(
          switchMap(passwordIsCorrect => passwordIsCorrect ? of(user) : throwError(new UnauthorizedException()))
        )
      })
    ).toPromise();
  }

但是,在這種情況下,您似乎正在努力使用可觀察對象(將 promise 轉換為可觀察對象,只是為了轉換回 promise )。

即使 userSerivce 返回 observable,為什么不直接將其轉換為 promise 呢? 看起來代碼會簡單得多:

  public async validateUser(email: string, pass: string): Promise<UserDto> {
    const user = await this.userService.findOne({ email }).toPromise();
    
    if (!user?.password || !await bcrypt.compare(pass, user.password)) {
      throw new UnauthorizedException();
    }
    
    return user;
  }

如果你真的不喜歡內部 pipe,你可以使用combineLatest傳遞user的值以及passwordIsCorrect

public validateUser(email: string, pass: string): Promise<UserDto> {
    return this.userService
      .findOne({ email })
      .pipe(
        map((user: UserDto) => {
          if (!user || !user.password) {
            return throwError(new UnauthorizedException());
          }
          return user;
        }),
        switchMap((user: UserDto) => {
          return combineLatest([
            from(bcrypt.compare(pass, user.password)),
            of(user)
          ])
        }),
        map(([passwordIsCorrect, user]) => ({
          passwordIsCorrect,
          user
        })),
        switchMap((res) => {
          if (!res.passwordIsCorrect) {
            return throwError(new UnauthorizedException());
          }
          return of(res.user);
        })
      )
      .toPromise();
  }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM