这个问题相似,但是答案是针对帆的:NodeJS best practices: Errors for flow control?
我来自从事C#REST API的工作背景。在C#中,当出现可操作的“错误”(我故意在引号中使用错误)时,我们只向消息查找表返回了一个常量或键。根据所返回的消息,路由层将向用户返回适当的状态代码(200、404等)。
进行登录。请考虑有人登录到服务器,并且该帐户不存在。这不是一件不寻常的事情,因此抛出错误没有多大意义。
现在,我正在编写Node应用程序,这让我感到沮丧。似乎常见的做法是在发生任何意外情况时将错误抛出到各处。对于诸如数据库无法检索已知存在的帐户失败或捕获语法错误之类的事情,这是有意义的。但是对于诸如用户输入错误的用户名/密码之类的东西,抛出错误似乎是过分的。
然后考虑您有错误报告中间件的情况。对于语法错误,当您永远不想为诸如错误的密码之类的操作进行记录时,可能要记录堆栈跟踪。通过使用错误进行控制流,输入错误密码的用户可能会消耗与记录关键数据库异常相同的服务器资源。您可以扩展Error类并打开错误的类型,但这似乎很草率。
最后,某些解决方案只是直接返回带有状态码的ExpressJS响应,但是对于在数据库中找不到用户的每种情况,我并不总是希望使用相同的状态码。也许我想为用户个人资料页面返回404,而对于登录失败返回400。
还有其他人遇到过这个问题吗?如果是这样,您是如何处理它的(双关语意)?
以下代码演示了我的解决方案。
我发明了一个名为Goof
的新类,它就像一个错误,但在可能会导致结果的情况下使用。例如,错误的登录凭据将是Goof
的一种类型:
// constants.js.
const WRONG_PASSWORD = 1;
const USERNAME_DOES_NOT_EXIST = 1;
// goof.js.
class Goof {
constructor(message) {
this.message = message;
}
}
// Inside express route.
const username = req.body.username;
const password = req.body.password;
const result = await signInUser(username, password);
if(typeof(result) === Goof) {
if(result.status === constants.WRONG_PASSWORD) {
res.sendStatus(400);
return;
}
if(result.status === constants.USERNAME_DOES_NOT_EXIST) {
res.sendStatus(400)
return;
}
else {
throw new Error('A Goof was returned but not handled properly');
}
} else {
res.json(result);
}
与抛出和捕获错误相比,此方法有什么优点/缺点?