javascript - 用这个简单的例子理解 Promise 链
问题描述
我需要以下逻辑,但我无法理解。当找到用户(不是 undefined
)时,我需要比较返回 a 的密码(另一个承诺boolean
)。需要:
undefined
当用户不存在时返回(HTTP 404)- 密码错误时抛出
ForbiddenError
(HTTP 403) user
当用户存在且密码匹配时返回(HTTP 200)
第一次尝试(丑陋,不可读):
@Post()
login(
@BodyParam('username', { required: true }) username: string,
@BodyParam('password', { required: true }) plainPassword: string,
) {
return this.userRepository.findOne({ username: username, enable: true })
.then ((user: User | undefined) => {
if (!user) {
return undefined; // 404
}
return bcrypt.compare(plainPassword, user.password)
.then(passwordMatch => {
if (!passwordMatch) {
throw new ForbiddenError('Authentication failed.'); // 403
}
return user; // 200
});
});
}
第二次尝试不起作用,总是返回'ok'
:
return this.userRepository.findOne({ username: username, enable: true })
.then((user: User | undefined) => {
if (!user) {
return undefined; // 404
}
return bcrypt.compare(password, user.password);
})
.then(passwordMatch => {
// Doesn't work: this is executed every time (even if user is undefined).
return 'ok';
});
解决方案
最后的then
处理程序总是运行(好吧,如果承诺不拒绝),因为如果用户不存在,则第一个承诺会解决undefined
,或者如果用户确实存在,则使用布尔值解决。
你的嵌套版本很好。如果您需要user
在成功的情况下返回,这可能是要走的路。
但是,如果您只需要'ok'
像在成功案例中的第二个代码示例中那样返回,您可以将事情展平,您只需要处理undefined
如果没有用户就会得到的。我们还可以利用这样一个事实,即如果找不到用户,您知道user
将具有价值:undefined
return this.userRepository.findOne({ username: username, enable: true })
// The `then` below returns `undefined` if `user` is `undefined`, the promise from `compare` otherwise
.then((user: User | undefined) => user && bcrypt.compare(password, user.password))
.then(passwordMatch => {
if (passwordMatch === undefined) {
// No user
return undefined;
} else if (!passwordMatch) {
// Bad password
throw new ForbiddenError('Authentication failed.'); // 403
} else {
// All good
return 'ok';
}
});
如果要将其展平并返回user
,则需要传播user
到下一个处理程序:
return this.userRepository.findOne({ username: username, enable: true })
.then((user: User | undefined) => {
return !user
? {user} // will be {undefined}
: bcrypt.compare(password, user.password)
.then(passwordMatch => ({user, passwordMatch})); // *** Note making an object
})
.then(({user, passwordMatch}) => { // *** Note destructuring
if (user === undefined) {
// No user
return undefined;
} else if (!passwordMatch) {
// Bad password
throw new ForbiddenError('Authentication failed.'); // 403
} else {
// All good
return user; // 200
}
});
(第一个then
处理程序可能是上面第一个代码块中的简洁箭头,但它开始变得丑陋。)
推荐阅读
- entity - 无法在应用程序用户表和我的表之间创建关系
- node.js - 使用 multer 从表单将图像上传到 nodejs
- python - 将 Kivy 应用程序编译为 Windows 可执行文件
- java - 如何使用 JUnit5 测试抽象接口?
- c++11 - Vulkan 描述符集最佳实践
- knockout.js - KnockoutJS:是否将一个 observble 数组作为参数传递给另一个绑定它们?
- angular - (角度 6)打开右侧导航时的图形错误
- javascript - JavaScript:创建未知维度多维数组函数时的引用传递问题
- go - 使用操作员框架对 K8s Pod 进行负载平衡
- android - 如何在cordova上设置后台服务以拒绝断开连接?