【问题标题】:switchMap operator doesn't execute the returned observableswitchMap 操作符不执行返回的 observable
【发布时间】:2021-12-08 14:23:16
【问题描述】:

我有一个 API (NestJS) 并尝试建立一个登录。它正在使用 TypeOrm 访问数据库。

当策略类调用auth.validateUser 方法时,我需要从数据库中获取一个用户并使用bcrypt 比较密码。问题是 switchMap 没有订阅返回的 observable。

这是我的代码:

auth.service.ts

validateUser(email: string, password: string): Observable<User> {
    return this.userService.readByEmail(email).pipe(
        switchMap(user => {
            return new Observable<User>(subscriber => {
                if (!user) {
                    subscriber.next(null)
                    subscriber.complete()
                } else {
                    bcrypt.compare(password + global.userPepper, user.password)
                        .then(result => {
                            const { password, ...validUser } = user
                            if (result) subscriber.next(validUser as User)
                            else subscriber.next(null)
                            subscriber.complete()
                        })
                        .catch(err => {
                            console.log(err)
                            subscriber.next(null)
                            subscriber.complete()
                        })
                }
            })
        })
    )
}

user.service.ts

readByEmail(email: string): Observable<User> {
    return new Observable<User>(subscriber => {
        // This part of the code is never executed
        this.userRepo.findOne({ email }).then(user => subscriber.next(user))
    })
}

问题是什么,我该如何解决?

更新:
userService.readByEmail 中的问题已按照Tobias S. 答案的建议解决。 但是没有调用来自authServiceswitchMap 运算符。我解决了这个问题,更改了调用我的auth.validateUser 的策略文件,以返回一个承诺而不是一个可观察的对象,并且可以正常工作。
local.strategy.ts
之前:

validate(email: string, password: string) {
    return this.auth.validateUser(email, password).pipe(
        map(user => {
            if (!user) {
                throw new UnauthorizedException()
            }

            return user
        })
    )
}

之后:

validate(email: string, password: string) {
    return this.auth.validateUser(email, password).pipe(
        map(user => {
            if (!user) {
                throw new UnauthorizedException()
            }

            return user
        })
    ).toPromise()
}

【问题讨论】:

    标签: typescript rxjs observable nestjs typeorm


    【解决方案1】:

    我认为这段代码可以进一步简化。你真的不需要使用new Observable() 自己创建任何 Observables。

    在 UserService 中,您可以简单地使用 from 运算符从 Promise 创建一个 Observable。

    user.service.ts

    readByEmail(email: string): Observable<User> {
        return from(this.userRepo.findOne({ email }))
    }
    

    在 AuthService 中,如果没有用户,您可以返回 EMPTY,然后返回您使用 bcrypt 创建的 Promise。

    If it accepts Observable, it accepts Promise

    auth.service.ts

    validateUser(email: string, password: string): Observable<User> {
        return this.userService.readByEmail(email).pipe(
            switchMap(user => {
                if (!user) return EMPTY
    
                return bcrypt.compare(password + global.userPepper, user.password)
                    .then(result => {
                        const { password, ...validUser } = user
                        if (result) return validUser as User
                     })
                    .catch(console.log)
            })
        )
    }
    

    【讨论】:

    • userService.readByEmail 中的 findOne 已执行。但任何管道都不是。我试图从 validateUser 记录 readByEmail 和 switchMap 以查看它是否正在运行,但只有在第一种情况下我才得到日志。其他运算符更合适吗?
    猜你喜欢
    • 2019-10-28
    • 1970-01-01
    • 2016-12-18
    • 1970-01-01
    • 2019-06-11
    • 1970-01-01
    • 2019-11-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多