javascript - არსებობს უკეთესი RXJs ოპერატორი, რომელიც გამოიყენება ამ სცენარში?
მე მაქვს სერვისის მეთოდი, რომელიც აკეთებს შემდეგს:
- ძებნის მომხმარებელს მონაცემთა ბაზაში მათი ID-ის მიხედვით
- ამოწმებს, პოვნა თუ მოხდა მომხმარებელი
- გამოყენებს bcrypt-ს, რათა შეადაროს მონაცემთა ბაზაში შენახული პაროლი, პარამეტრის სახით მიწოდებულ პაროლთან
- ინახავს 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();
}
უპასუხე #1
ვერ ვფიქრობ, რომ არსებობს უკეთესი ოპერატორი გამოსაყენებლად, მაგრამ შეგიძლიათ კოდი ასეთად შეაჯამოთ, რომ ყველაფერი ერთ 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();
}
თუმცა, ამ შემთხვევაში, ჩანს, რომ თქვენ ბრძოლა გჭირდებათ observables-ის გამოყენებისთვის, (პრომისის კონვერტირება observable-ში, მხოლოდ იმისთვის, რომ ისევ პრომისად გადააკეთოთ).
უწლებლად თუ 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;
}
პასუხი #2
თუ ნამდვილად არ მოგწონს შიდა მილაკი, შეგიძლიათ გამოიყენოთ 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();
}
