在这种情况下是否有更好的 RXJs Operator 可以使用?
Is there a better RXJs Operator to use in this scenario?
我有一个执行以下操作的服务方法:
- 通过 ID 从数据库中查找用户
- 检查是否找到用户
- 使用 bcrypt 将存储在数据库中的密码与作为参数提供的密码进行比较
- 如果密码不正确,则抛出 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;
}
我有一个执行以下操作的服务方法:
- 通过 ID 从数据库中查找用户
- 检查是否找到用户
- 使用 bcrypt 将存储在数据库中的密码与作为参数提供的密码进行比较
- 如果密码不正确,则抛出 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;
}