我正在使用我的 Express 应用程序编写登录函数,但不喜欢回调链中大量重复的 res.status(500).send(body)
:
router.post('/login', (req, res) => {
User.findOne({
where: { username: req.body.username }
})
.then( user => {
if (user) {
User.verifyPassword(req.body.password, user)
.then((verified) => {
if (verified) {
let signedToken = jwt.sign(
{ user: user.id },
'secret',
{ expiresIn: 24 * 60 * 60 }
);
res.status(200).send({
token: signedToken,
userId: user.id,
username: user.username
});
} else {
// If password entered does not match user password
res.status(500).send({ error: true, });
}
})
// If bycrpt explodes
.catch((error) => {
res.status(500).send({ error: error, });
});
} else {
// If we can't even find a user with that username
res.status(500).send({ error: true, });
}
})
// If the db query to find a user explodes
.catch(error => {
res.status(500).send({ error: error });
});
});
其中两个与发生的模糊异常有关,这些异常会导致 API 崩溃。另外两个基于 API 返回的 bool 值。 我不是一个后端工程师,这只是一个个人项目,但我想知道 Node.js 世界中的最佳实践是什么。
当我们这样做时,我不确定在这些错误情况下发送的适当状态代码是什么,因为我确信 500 不正确。
最佳答案
我会像这样重写你的代码,其中我们只有一个.catch
router.post('/login', (req, res) => {
User.findOne({ where: { username: req.body.username }})
.then(user => {
if (!user) // If we can't even find a user with that username
return Promise.reject(true); // You should probably return an Error
return User.verifyPassword(req.body.password, user)
})
.then((verified) => {
if (!verified) // If password entered does not match user password
return Promise.reject(true); // You should probably return an Error
let signedToken = jwt.sign({
user: user.id
},
'secret', {
expiresIn: 24 * 60 * 60
}
);
res.status(200).send({
token: signedToken,
userId: user.id,
username: user.username
});
}).catch(error => {
// If the db query to find a user explodes
// If we can't even find a user with that username
// If password entered does not match user password
// You could throw different errors and handle
// all of them differently here
res.status(500).send({
error: error
});
});
});
可以使用async/await
进一步改进
router.post('/login', async(req, res) => {
try {
const user = await User.findOne({ where: { username: req.body.username }});
if (!user) // If we can't even find a user with that username
throw new Error('Invalid username');
const verified = await User.verifyPassword(req.body.password, user)
if (!verified) // If password entered does not match user password
throw new Error('Invalid password');
let signedToken = jwt.sign({
user: user.id
},
'secret', {
expiresIn: 24 * 60 * 60
}
);
res.status(200).send({
token: signedToken,
userId: user.id,
username: user.username
});
} catch(error) {
// If the db query to find a user explodes
// If we can't even find a user with that username
// If password entered does not match user password
res.status(500).send({
error: error.message
});
}
});
关于状态码,有多种处理方法,我通常为每个状态码抛出一个特定的错误。
errors.js
class Unauthorized extends Error {
constructor(message) {
super(message);
this.name = 'UnauthorizedError';
this.statusCode = 401
}
}
class BadRequest extends Error {
constructor(message) {
super(message);
this.name = 'BadRequestError';
this.statusCode = 400
}
}
/** more errors... **/
module.exports = {
Unauthorized,
BadRequest
};
现在我们可以设置正确的状态代码:
const { Unauthorized } = require('./errors');
/* ... */
try {
/* ... */
if (!verified) // Some people may say 422 status code...
throw new Unauthorized('Invalid password');
/* ... */
} catch(error) {
res.status(error.statusCode || 500).send({
error: error.message
});
}
While we're at it, I'm not sure what the appropriate status code to send in these error cases would be, as I am sure 500 is not correct.
你是对的,为每个错误设置 500 是不正确的。我将留给您几个问题,可能会帮助您设置正确的状态代码,因为在这个问题中讨论它的时间太长了。
What's an appropriate HTTP status code to return by a REST API service for a validation failure?
关于node.js - 在 express 发送错误时防止代码重复的最有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49744549/