在这种情况下是否有更好的RXJs操作符?



我有一个服务方法,它做以下事情:

  1. 根据用户ID从数据库中查找用户
  2. 检查是否找到了用户
  3. 使用bcrypt比较存储在DB中的密码与作为参数
  4. 提供的密码
  5. 如果密码不正确则抛出UnauthorizedException,如果正确则返回用户。

我只是想找出是否有更好的方法使用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();
}

我不认为有一个更好的操作符使用,但你可以简化代码,所有在相同的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)。

即使userservice返回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;
}

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

最新更新