JavaScript尝试/捕获:错误还是异常?
嗯。我可能在这里吹毛求疵,但我的代码不一致,我希望这样做。但在我这么做之前,我想确定我走的是正确的道路。实际上这并不重要,但这已经困扰了我一段时间,所以我想我应该问问我的同龄人 每次我使用JavaScript尝试/捕获:错误还是异常?,javascript,error-handling,nomenclature,Javascript,Error Handling,Nomenclature,嗯。我可能在这里吹毛求疵,但我的代码不一致,我希望这样做。但在我这么做之前,我想确定我走的是正确的道路。实际上这并不重要,但这已经困扰了我一段时间,所以我想我应该问问我的同龄人 每次我使用时,请尝试。。。catch语句,在catch块中,我总是将消息记录到我的内部控制台。但是,我的日志消息不一致。它们要么看起来像: catch(err) { DFTools.console.log("someMethod caught an error: ",err.message); ... 或: 显然,无论
时,请尝试。。。catch
语句,在catch块中,我总是将消息记录到我的内部控制台。但是,我的日志消息不一致。它们要么看起来像:
catch(err) {
DFTools.console.log("someMethod caught an error: ",err.message);
...
或:
显然,无论哪种方式,代码都能正常运行,但我有时会提到“错误”,有时会提到“异常”,这让我开始感到困扰。就像我说的,也许我在吹毛求疵,但哪个术语才是正确的呢?“异常”或“错误”?在Catch块中得到的是异常,因此我将其命名为异常 如果是错误,我可以在代码中处理它&我通常不希望在Catch块中看到它
HTH.异常是您可能期望的情况,例如,在尝试打开文件时可能会遇到“未找到文件异常”。另一方面,错误是您可能看不到的,比如堆栈溢出或内存不足
异常是不产生逻辑结果的函数的另一种逻辑输出方式。例外情况也可以更好地解释为什么它以这种方式存在。对于文件打开,文件句柄也是一个逻辑结果,如果文件不存在(一个可能的异常)或者它是一个文件夹而不是文件(另一个可能的异常)。在JavaScript中称为错误捕获。所以我建议您使用错误而不是异常。 中间选择“E”。就像Mozilla的例子一样。
这有点主观,但对我来说,错误是指某人或某事做错、不恰当或无效的事情。它可能是语法错误、逻辑错误、读取错误、用户错误,甚至是社交错误。这是一个抽象的概念 另一方面,异常是在代码中出现特定条件时创建并抛出的对象。它可能对应于也可能不对应于概念错误。所以对我来说,正确的命名法是“例外”。他们称之为例外。你可能也想这样做 要使日志记录更具信息性,请执行以下操作:
catch(ex) {
DFTools.console.log("someMethod caught an exception of type "
+ ex.name + ": ", ex.message);
您可能还需要记住,异常(不幸的是)可以是任何类型的,因此不一定具有name
和message
属性:
catch(ex) {
if (ex.message && ex.name) {
DFTools.console.log("someMethod caught an exception of type "
+ ex.name + ": ", ex.message);
} else /* deal with it somehow */
由于在任何地方重复这项操作都显得非常麻烦,您可能希望在函数中捕获它:
function logExceptions(methodName, action) {
try {
action();
} catch (ex) {
if (ex.message && ex.name) {
DFTools.console.log("someMethod caught an exception of type "
+ ex.name + ": ", ex.message);
} else {
DFTools.console.log("someMethod caught a poorly-typed exception: " + ex);
}
}
}
现在你可以说:
logExceptions(function() {
// do some risky stuff...
});
主要的免责声明:我不认为这个问题有一个“正确”的答案。这里表达的观点是主观和个人的。更重要的是,我要支持的想法只有在你用不同的错误做不同的事情时才有用。。。正如你可能会使用一个系统,根据丹尼尔·埃尔威克的信息性回答。考虑到这一点:
我主张“例外是例外”。一个错误是不那么意外的
免责声明:以下伪代码不好;这只是我能想到的最起码的例子来说明我的观点
注意:在这个思维实验中,如果找不到指定的文件,GetFile将返回UNDEFINED
function AlwaysGetFile(name){
var file = null;
if(FileExists(name)){
file = GetFile(name);
if(typeof file === "undefined"){
throw new "couldn't retrieve file" EXCEPTION
}
}
else{
throw new "file does not exist" ERROR
}
return file;
}
如果使用者使用不存在的文件名调用GetFileOrThrow,则会发生错误。在我看来,区别实际上是更高级别的代码(或用户输入)做错了什么。。。此函数必须向上传递一个错误到更高级别的代码,该代码可以决定如何处理此结果。这样想吧…此函数将对任何消费函数表示:
听着,我的朋友,我知道这里发生了什么:请求BobAccounts.xml是一个错误,所以不要再这样做了!哦,如果你认为你现在知道可能出了什么问题(虐待了我),那就去努力从中恢复过来吧
现在考虑这个函数取名称的情况,检查文件是否存在,然后由于某种原因无法检索它。这是另一种情况。出人意料的事情发生了。更重要的是,消费代码不是罪魁祸首。现在我们真的想让这个函数对任何消费函数说:
哦,小提琴!很抱歉,我谦恭地请求您的原谅,但我真的不明白有什么异常情况出了问题。我不认为您对BobAccounts.xml的请求是不合理的。。。我知道我应该为你实现它。因为我的代码级别比你低,我真的应该知道发生了什么。。。但我不。。。既然你比我了解这种特殊情况的机会少,我想你最好停止你正在做的事情,让这条信息一直传到最高层。。。我是说,这里发生了一些非常可疑的事情 所以我想我的总结是这样的:如果错误发生在高阶代码中(您被传递了坏数据),抛出一个错误。如果错误发生在低阶代码中(您所依赖的函数以您不理解且无法计划的方式失败),则抛出异常。。。如果错误发生在您当前编写的函数中。。。嗯,如果你知道的话,那就把它修好最后,为了更直接地回答最初的问题:在处理错误和异常方面,我的建议是:优雅地处理所有错误(可以选择记录错误)。。。但确实要小心处理例外情况,;只有当您确实知道异常是什么以及发生的原因时,才尝试从异常中恢复,否则就让它冒泡(如果必须的话,请重新刷新它)。我一直将此称为“异常处理”,但要触发捕获块,您将抛出新错误(“…”),所以…你可以扔你想要的任何东西-
扔“嗨,妈妈!”代码>完全有效。是。也许
function AlwaysGetFile(name){
var file = null;
if(FileExists(name)){
file = GetFile(name);
if(typeof file === "undefined"){
throw new "couldn't retrieve file" EXCEPTION
}
}
else{
throw new "file does not exist" ERROR
}
return file;
}