Typescript 需要将可观察到的过去2个结果作为输入到第三个
有没有一种方法可以从一个可观察的序列中获得过去的两个结果,并将其作为第三个序列的输入 这是没有任何可见项的代码Typescript 需要将可观察到的过去2个结果作为输入到第三个,typescript,rxjs,Typescript,Rxjs,有没有一种方法可以从一个可观察的序列中获得过去的两个结果,并将其作为第三个序列的输入 这是没有任何可见项的代码 public login(...): Promise<any> { const user: any = ctx.prisma.query.user({ where: { email } }); if (!user) { throw new Error(`No such user found for email: ${email}`);
public login(...): Promise<any> {
const user: any = ctx.prisma.query.user({ where: { email } });
if (!user) {
throw new Error(`No such user found for email: ${email}`);
}
const valid = bcrypt.compare(password, user.password);
if (!valid) {
throw new Error("Invalid password");
}
return {
token: jwt.sign({ userId: user.id }, process.env.APP_SECRET),
user,
};
}
这是我尝试的有效解决方案,但我只是想知道这是正确的还是有更好的方法 我需要
用户
和有效的
结果生成我的映射
,以便创建正确的对象
我的解决方案感觉很奇怪,因为如果我需要继续这个序列和之前的结果,它会变得非常深入
public login(...): Promise<any> {
return from(ctx.prisma.query.user({ where: { email } })).pipe(
switchMap(
(user: User) => {
if (!user) {
throw new Error(`No such user found for email: ${email}`);
}
return from(bcrypt.compare(password, user.password)).pipe(
map(
(valid: boolean) => {
if (!valid) {
throw new Error("Invalid password");
}
return {
token: jwt.sign({ userId: user.id }, process.env.APP_SECRET),
user,
};
}
)
);
}
)
).toPromise();
}
公共登录(…):承诺{
从(ctx.prisma.query.user({where:{email}}]).pipe返回(
开关图(
(用户:用户)=>{
如果(!用户){
抛出新错误(`没有为电子邮件找到这样的用户:${email}`);
}
从(bcrypt.compare(password,user.password)).pipe返回(
地图(
(有效:布尔)=>{
如果(!有效){
抛出新错误(“无效密码”);
}
返回{
令牌:jwt.sign({userId:user.id},process.env.APP_SECRET),
用户,
};
}
)
);
}
)
).toPromise();
}
switchMap是您想要的运算符,switchMap的第二个参数是一个map函数,它接受内部和外部可观察的结果,并允许您将它们组合起来(mergemap接受相同的第二个参数,但首选switchMap,因为它是“更安全”的运算符):
公共登录(…):承诺{
从(ctx.prisma.query.user({where:{email}}]).pipe返回(
开关图(
(用户:用户)=>{
如果(!用户){
抛出新错误(`没有为电子邮件找到这样的用户:${email}`);
}
从(bcrypt.compare(password,user.password))返回;
}
,(用户,有效)=>{
如果(!有效){
抛出新错误(“无效密码”);
}
返回{
令牌:jwt.sign({userId:user.id},process.env.APP_SECRET),
用户,
};
}
)).toPromise();
}
switchMap是您想要的运算符,switchMap的第二个参数是一个map函数,它接受内部和外部可观察的结果,并允许您将它们组合起来(mergemap接受相同的第二个参数,但首选switchMap,因为它是“更安全”的运算符):
公共登录(…):承诺{
从(ctx.prisma.query.user({where:{email}}]).pipe返回(
开关图(
(用户:用户)=>{
如果(!用户){
抛出新错误(`没有为电子邮件找到这样的用户:${email}`);
}
从(bcrypt.compare(password,user.password))返回;
}
,(用户,有效)=>{
如果(!有效){
抛出新错误(“无效密码”);
}
返回{
令牌:jwt.sign({userId:user.id},process.env.APP_SECRET),
用户,
};
}
)).toPromise();
}
在您的解决方案中,您可以做一些事情来避免所有级别的嵌套,但在我看来,您所拥有的并没有错
我所做的第一个更改是使用点击
进行错误检查。这真的只是为了外观,尽管我猜检查地图中的错误感觉是错误的
接下来,将开关映射
更改为采用结合检索到的用户值和解密结果的forkJoin
。forkJoin
是我所能想到的最干净的方法,可以让用户在序列中走得更远
其余的都很简单
from(ctx.prisma.query.user({ where: { email } })).pipe(
tap(user => { if (!user) throw new Error(`No such user found for email: ${email}`); }),
switchMap(user => forkJoin(of(user), from(bcrypt.compare(password, user.password))),
tap(([user, valid]) => { if (!valid) throw new Error('Invalid password'); })
map(([user, valid]) => ({
token: jwt.sign({ userId: user.id }, process.env.APP_SECRET),
user,
}))
)
在您的解决方案中,您可以做一些事情来避免所有级别的嵌套,但在我看来,您所做的并没有错 我所做的第一个更改是使用
点击
进行错误检查。这真的只是为了外观,尽管我猜检查地图中的错误感觉是错误的
接下来,将开关映射
更改为采用结合检索到的用户值和解密结果的forkJoin
。forkJoin
是我所能想到的最干净的方法,可以让用户在序列中走得更远
其余的都很简单
from(ctx.prisma.query.user({ where: { email } })).pipe(
tap(user => { if (!user) throw new Error(`No such user found for email: ${email}`); }),
switchMap(user => forkJoin(of(user), from(bcrypt.compare(password, user.password))),
tap(([user, valid]) => { if (!valid) throw new Error('Invalid password'); })
map(([user, valid]) => ({
token: jwt.sign({ userId: user.id }, process.env.APP_SECRET),
user,
}))
)
在@bryan60和@Daniel Gimenez的帮助下,我们得出结论,我在问题中提供的解决方案在版本6中是最准确的。这是我的最终解决方案
public login(
source: any,
{email, password},
ctx: IContext,
info: GraphQLResolveInfo): Promise<any> {
return from(ctx.prisma.query.user({ where: { email } })).pipe(
tap(
(user: User) => {
if (!user) {
throw new Error(`No such user found for email: ${email}`);
}
}
),
switchMap(
(user: User) => {
return from(bcrypt.compare(password, user.password)).pipe(
map(
(valid: boolean) => {
if (!valid) {
throw new Error("Invalid password");
}
return {
token: jwt.sign(
{ userId: user.id },
process.env.APP_SECRET
),
user,
};
}
)
);
}
)
).toPromise();
}
公共登录(
资料来源:任何,
{电子邮件,密码},
ctx:IContext,
信息:GraphQLResolveInfo):承诺{
从(ctx.prisma.query.user({where:{email}}]).pipe返回(
水龙头(
(用户:用户)=>{
如果(!用户){
抛出新错误(`没有为电子邮件找到这样的用户:${email}`);
}
}
),
开关图(
(用户:用户)=>{
从(bcrypt.compare(password,user.password)).pipe返回(
地图(
(有效:布尔)=>{
如果(!有效){
抛出新错误(“无效密码”);
}
返回{
令牌:jwt.sign(
{userId:user.id},
process.env.APP_SECRET
),
用户,
};
}
)
);
public login(
source: any,
{email, password},
ctx: IContext,
info: GraphQLResolveInfo): Promise<any> {
return from(ctx.prisma.query.user({ where: { email } })).pipe(
tap(
(user: User) => {
if (!user) {
throw new Error(`No such user found for email: ${email}`);
}
}
),
switchMap(
(user: User) => {
return from(bcrypt.compare(password, user.password)).pipe(
map(
(valid: boolean) => {
if (!valid) {
throw new Error("Invalid password");
}
return {
token: jwt.sign(
{ userId: user.id },
process.env.APP_SECRET
),
user,
};
}
)
);
}
)
).toPromise();
}