cib*_*cib 23 javascript rest exception-handling node.js async-await
在处理REST API调用的此函数中,处理部分请求的任何被调用函数都可能抛出错误,表示应将错误代码作为响应发送.但是,函数本身也可能发现错误,此时它应该跳转到异常处理块.
static async handleRequest(req) {
try {
let isAllowed = await checkIfIsAllowed(req);
if (!isAllowed) {
throw new ForbiddenException("You're not allowed to do that.");
}
let result = await doSomething(req); // can also raise exceptions
sendResult(result);
} catch(err) {
sendErrorCode(err);
}
}
Run Code Online (Sandbox Code Playgroud)
Webstorm将throw使用以下消息强调:'throw' of exception caught locally. This inspection reports any instances of JavaScript throw statements whose exceptions are always caught by containing try statements. Using throw statements as a "goto" to change the local flow of control is likely to be confusing.
但是,我不确定如何重构代码来改善这种情况.
我可以将catch块中的代码复制到if检查中,但我相信这会使我的代码不易读取并且难以维护.
我可以编写一个新函数来执行isAllowed检查,如果不成功则抛出异常,但这似乎是回避问题,而不是修复Webstorm据称报告的设计问题.
我们是否以错误的方式使用异常,这就是为什么我们遇到这个问题,或者Webstorm错误只是误导而应该被禁用?
J. *_*son 39
与 James Thorpe 的观点相反,我稍微更喜欢投掷的模式。我没有看到任何令人信服的理由来对待 try 块中的本地错误与从调用堆栈更深处冒出的错误有任何不同……只是抛出它们。在我看来,这是一致性的更好应用。
因为这种模式更加一致,所以当您想要将 try 块中的逻辑提取到可能位于另一个模块/文件中的另一个函数时,它自然更适合重构。
// main.js
try {
if (!data) throw Error('missing data')
} catch (error) {
handleError(error)
}
// Refactor...
// validate.js
function checkData(data) {
if (!data) throw Error('missing data')
}
// main.js
try {
checkData(data)
} catch (error) {
handleError(error)
}
Run Code Online (Sandbox Code Playgroud)
如果不是在 try 块中处理错误,而是在 try 块之外对其进行重构,则逻辑必须更改。
此外,处理错误的缺点是让你记得提前返回,这样 try 块在遇到错误后不会继续执行逻辑。这很容易忘记。
try {
if (!data) {
handleError(error)
return // if you forget this, you might execute code you didn't mean to. this isn't a problem with throw.
}
// more logic down here
} catch (error) {
handleError(error)
}
Run Code Online (Sandbox Code Playgroud)
如果您担心哪种方法性能更好,那么您不应该担心。处理错误在技术上更高效,但两者之间的区别绝对微不足道。
考虑一下 WebStorm 在这里有点过于固执的可能性。ESLint 对此甚至没有规定。这两种模式都是完全有效的。
Jam*_*rpe 26
如果isAllowed失败,你正在检查某些事情并抛出异常,但是你知道在那种情况下该怎么办 - 打电话sendErrorCode.如果你不知道如何处理这种情况,你应该向外部呼叫者抛出异常 - 即在特殊情况下.
在这种情况下,如果发生这种情况,您已经有了一个已定义的过程 - 只需直接使用它而不使用间接throw/catch:
static async handleRequest(req) {
try {
let isAllowed = await checkIfIsAllowed(req);
if (!isAllowed) {
sendErrorCode("You're not allowed to do that.");
return;
}
let result = await doSomething(req); // can also raise exceptions
sendResult(result);
} catch(err) {
sendErrorCode(err);
}
}
Run Code Online (Sandbox Code Playgroud)
我可以将
catch块中的代码复制到if检查中,但我相信这会使我的代码不易读取并且难以维护.
相反,如上所述,我希望这是处理这种情况的方法.
Slo*_*man 12
既然这不是阻塞错误,而只是IDE建议,那么问题应该从两个方面来看。
第一面是性能。如果这是一个瓶颈,并且有可能将其用于编译或转移到新的(尚未发布的)nodejs 版本时,重复的存在并不总是一个糟糕的解决方案。在这种情况下,IDE 似乎准确地暗示了这种设计,并且在某些情况下,这种设计可能会导致优化不佳。
第二个方面是代码设计。如果它会使代码更具可读性并简化其他开发人员的工作 - 保留它。从这个角度来看,上面已经提出了解决方案。
在 try 块中返回一个 promise 拒绝而不是抛出错误
try {
const isAllowed = await checkIfIsAllowed(request);
if (!isAllowed) {
return Promise.reject(Error("You're not allowed to do that."));
}
const result = await doSomething(request);
sendResult(result);
} catch (error) {
throw error;
}
Run Code Online (Sandbox Code Playgroud)