javascript - 我的代码是使用异步等待的最佳方式吗?
问题描述
我尝试async await functions
在我的登录示例中实现和学习,但我不知道是否是最好、优雅和干净的代码。我在捕获错误方面有疑问,如果我需要以最佳方式实现 const 和函数式编程。可以分享你的意见吗?
app.post('/', async (req, res) => {
try {
const { email } = req.body.email; // destructuring
const usuarioEncontrado = await Usuario.findOne({email: email});
// Validate user exist
if (!usuarioEncontrado) { // when not exist return null
throw res.status(404).json({error: 'El usuario no existe'});
}
// validate user pass
if (!bcrypt.compareSync(req.body.password, usuarioEncontrado.password)) {
throw res.status(404).json({error: 'No match'});
}
const token = jwt.sign( // generate token
{
usuario: usuarioEncontrado
},
SEED,
{
expiresIn: (60 * 60)
}
);
res.status(200).json({ // send response
token: token,
usuario: usuarioEncontrado
});
} catch (e) { // send error
res.status(404).json(e);
}
}
谢谢
解决方案
您的代码显示了几个问题:
您正在尝试发送双重响应。首先你做 throw
res.status(404).json(...)
。然后,您捕获该异常并res.status(404).json(e)
再次执行。那是不对的。如果您要发送响应,则只需返回,不要抛出。或者,只是抛出异常而不发送响应,并从 catch 处理程序发送实际的错误响应。此外,
throw res.status(404).json({error: 'No match'});
发送响应,然后抛出.json()
可能不是您想要的任何返回。这不会是任何类型的错误对象。
我更喜欢将我发送错误响应的地方集中到请求处理程序中的一个地方。这使您永远不会尝试发送多个响应,并且只会使请求处理程序的流程更易于理解(在我看来)。
为此,我只是throw
一个自定义错误,它可能具有与之关联的自定义消息/状态,然后在一个地方捕获所有可能的错误。这是一种方法。该类myError
可以在您的项目中的任何地方使用,而不是特定于一条路线。这个想法是,通常当您throw
在该上下文中知道您想要的状态和消息是什么时,您可以在自定义 Error 对象中设置它,然后可以在 catch 中使用该信息。然后,catch 必须确定它是否有您的自定义错误或只是一个常规错误。首先,我有一个可重用的 Error 子类,它不仅可以抛出消息,还可以抛出状态值。
// reusable error class that contains a status in addition to the message
class MyError extends Error {
// this static method saves having to compare if it's a custom error object or not
// every time we use this
static sendError(res, e, status = 500) {
if (e instanceof MyError) {
e.sendError(res);
} else {
res.sendStatus(status);
}
}
constructor(msg, status = 500) {
// allow calling with or without new
if (!(this instanceof MyError)) {
return new MyError(msg, status);
}
super(msg);
this.status = status;
}
sendError(res) {
res.status(this.status).send(this.message);
}
}
然后,这是您在代码中使用它并集中发送错误状态的方法。
app.post('/', async (req, res) => {
try {
const { email } = req.body.email; // destructuring
const usuarioEncontrado = await Usuario.findOne({email: email});
// Validate user exist
if (!usuarioEncontrado) { // when not exist return null
throw MyError('El usuario no existe', 404);
}
// validate user pass
if (!bcrypt.compareSync(req.body.password, usuarioEncontrado.password)) {
throw MyError('No Match', 404);
}
const token = jwt.sign( // generate token
{
usuario: usuarioEncontrado
},
SEED,
{
expiresIn: (60 * 60)
}
);
res.status(200).json({ // send response
token: token,
usuario: usuarioEncontrado
});
} catch (e) { // log and send error response
// e may be either MyError or some other system generated Error
console.log(e);
MyError.sendError(res, e);
}
}
推荐阅读
- python - 我有一个错误:[WinError 2] 系统找不到指定的文件
- c++ - 使用 C++ 中的 EVP API 使用 OpenSSL 的 AES CBC 128 位解密失败
- python-3.x - 语义分割的自定义指标
- python - 有没有其他方法可以在 python 中定义动态变量,如 ['x' num2str(i)]?
- html - 有没有办法在线性渐变中指定角点?
- html - 导航栏溢出
- sql-server - 在子表上使用 IN () 删除 2 行创建的匹配行数为 1.97 亿行
- java - 错误填充异常
- r - 从 R 中的数据框中的 URL 列表中抓取网页
- android - 从 C 程序运行 android 脚本