在这种情况下是否有更好的 RXJs Operator 可以使用?

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

我有一个执行以下操作的服务方法:

  1. 通过 ID 从数据库中查找用户
  2. 检查是否找到用户
  3. 使用 bcrypt 将存储在数据库中的密码与作为参数提供的密码进行比较
  4. 如果密码不正确,则抛出 UnauthorizedException,returns 如果密码正确,则抛出用户。

我只是想看看是否有更好的方法使用 RxJS 运算符来执行此操作,因为我不喜欢从 bcrypt.compare:

进行管道传输
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();
  }

如果实在不喜欢内管,也可以用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();
  }

我认为没有更好的运算符可以使用,但您可以将代码简化为都在同一个 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 转换为 observable,只是为了转换回 promise)。

即使 userSerivce returns 可观察,为什么不直接将其转换为 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;
  }