如何在javascript中链接异常(如在java中添加原因)
是否有标准/最佳实践方法可以在javascript中添加异常原因。在java中,您可以执行以下操作:如何在javascript中链接异常(如在java中添加原因),java,javascript,node.js,error-handling,Java,Javascript,Node.js,Error Handling,是否有标准/最佳实践方法可以在javascript中添加异常原因。在java中,您可以执行以下操作: Throwable t = new Exception("whatever"); t.addCause(previouslyCaughtException); throw t; 当打印出结果异常时,它将为您提供一个包含原因的良好跟踪。在javascript中有什么好方法可以做到这一点,或者我必须自己动手吗?现在(直到有更好的答案),这就是我所做的: ... } catch(e) { thr
Throwable t = new Exception("whatever");
t.addCause(previouslyCaughtException);
throw t;
当打印出结果异常时,它将为您提供一个包含原因的良好跟踪。在javascript中有什么好方法可以做到这一点,或者我必须自己动手吗?现在(直到有更好的答案),这就是我所做的:
...
} catch(e) {
throw new Error("My error message, caused by: "+e.stack+"\n ------The above causes:-----")
}
我打印异常的方式使它看起来既漂亮又干净:
console.log(e.stack)
打印如下内容:
My error message: SomeError
<some line>
<more lines>
------The above causes:-----
<some line>
<more lines>
let ff = v => JSON.stringify(v, undefined, 4);
const formatForOutput = v => {
try {
return ff(v).replace(/\n/g, '\n ');
} catch (e) {
return "" + v;
}
};
const chainErrors = exporting.chainErrors = (e1, e2) => {
if (e1 instanceof Error)
e2.stack += '\nCaused by: ' + e1.stack;
else
e2.stack += '\nWas caused by throwing:\n ' + formatForOutput(e1);
return e2;
}
function someErrorThrowingFunction() {
throw new Error("Some Message");
}
function testOtherFnc() {
try {
someErrorThrowingFunction();
} catch (e) {
throw chainErrors(e, new Error("Some new Message"));
}
}
const Error = (() => {
const glob = (() => { try { return window; } catch (e) { return global; } })();
const isErrorExtensible = (() => {
try {
// making sure this is an js engine which creates "extensible" error stacks (i.e. not firefox)
const stack = (new glob.Error('Test String')).stack;
return stack.slice(0, 26) == 'Error: Test String\n at ';
} catch (e) { return false; }
})();
const OriginalError = glob.Error;
if (isErrorExtensible) {
let ff = v => JSON.stringify(v, undefined, 4);
const formatForOutput = v => {
try {
return ff(v).replace(/\n/g, '\n ');
} catch (e) {
return "" + v;
}
};
const chainErrors = (e1, e2) => {
if (e1 instanceof OriginalError)
e2.stack += '\nCaused by: ' + e1.stack;
else
e2.stack += '\nWas caused by throwing:\n ' + formatForOutput(e1);
return e2;
}
class Error extends OriginalError {
constructor(msg, chained) {
super(msg);
if (arguments.length > 1)
chainErrors(chained, this);
}
}
return Error;
} else
return OriginalError; // returning the original if we can't chain it
})();
我的错误消息:SomeError
------上述原因:-----
如果该行显示“原因”,可能会更好,因为首先打印导致错误的异常的堆栈跟踪 如果使用Node.js,则可以使用 Joyent还有一个页面讨论Node.js中错误处理的最佳实践 唯一的问题是,如果传入null或未定义的参数,我不喜欢Joyent对VError的实现是如何失败的。这在处理错误时尤为重要,因为它只会掩盖问题的根本原因。我已经分叉了它们的VError,所以它不会因为null或未定义的参数而失败。 在产品中,我们使用 用法 输出
您可以链接错误对象
Error
执行堆栈
和消息
var控制台={
日志:函数{
document.getElementById(“控制台”).innerHTML+=s+“
”
}
}
var error1=新错误(“这是错误1”);
console.log(“消息:”.concat(error1.Message));
console.log(“Stack
”.concat(error1.Stack));
var error2=新错误(“这是错误2”);
console.log(“消息:”.concat(error2.Message));
console.log(“Stack
”.concat(error2.Stack));
var error3=新错误(“这是错误3”);
error3.stack=error3.stack.concat(error2.stack).concat(error1.stack)
console.log(“消息:”.concat(error3.Message));
console.log(“Stack
”.concat(error3.Stack))代码>
tl;dr在ECMA脚本采用某些标准之前,这不是一个解决方案,只是一个助手。
编辑:我将这个答案包装到npm包中
这是一个很难的话题。原因是,ECMA脚本定义中没有关于堆栈跟踪的定义(甚至在中也没有)。因此,一些引擎实现了它们自己的堆栈跟踪及其表示思想
其中许多实现了Error.prototype.stack
属性,它是堆栈跟踪的字符串表示形式。由于未定义,因此不能依赖字符串格式。幸运的是,V8引擎非常常见(谷歌Chrome和NodeJS),这让我们至少有机会尝试一下
V8(以及使用它的应用程序)的一个优点是堆栈跟踪具有一种通用格式:
/path/to/file/script.js:11
throw new Error("Some new Message", e);
^
Error: Some new Message
at testOtherFnc (/path/to/file/script.js:69:15)
at Object.<anonymous> (/path/to/file/script.js:73:1)
at Module._compile (internal/modules/cjs/loader.js:688:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:699:10)
at Module.load (internal/modules/cjs/loader.js:598:32)
at tryModuleLoad (internal/modules/cjs/loader.js:537:12)
at Function.Module._load (internal/modules/cjs/loader.js:529:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:741:12)
at startup (internal/bootstrap/node.js:285:19)
at bootstrapNodeJSCore (internal/bootstrap/node.js:739:3)
您可以这样使用:
My error message: SomeError
<some line>
<more lines>
------The above causes:-----
<some line>
<more lines>
let ff = v => JSON.stringify(v, undefined, 4);
const formatForOutput = v => {
try {
return ff(v).replace(/\n/g, '\n ');
} catch (e) {
return "" + v;
}
};
const chainErrors = exporting.chainErrors = (e1, e2) => {
if (e1 instanceof Error)
e2.stack += '\nCaused by: ' + e1.stack;
else
e2.stack += '\nWas caused by throwing:\n ' + formatForOutput(e1);
return e2;
}
function someErrorThrowingFunction() {
throw new Error("Some Message");
}
function testOtherFnc() {
try {
someErrorThrowingFunction();
} catch (e) {
throw chainErrors(e, new Error("Some new Message"));
}
}
const Error = (() => {
const glob = (() => { try { return window; } catch (e) { return global; } })();
const isErrorExtensible = (() => {
try {
// making sure this is an js engine which creates "extensible" error stacks (i.e. not firefox)
const stack = (new glob.Error('Test String')).stack;
return stack.slice(0, 26) == 'Error: Test String\n at ';
} catch (e) { return false; }
})();
const OriginalError = glob.Error;
if (isErrorExtensible) {
let ff = v => JSON.stringify(v, undefined, 4);
const formatForOutput = v => {
try {
return ff(v).replace(/\n/g, '\n ');
} catch (e) {
return "" + v;
}
};
const chainErrors = (e1, e2) => {
if (e1 instanceof OriginalError)
e2.stack += '\nCaused by: ' + e1.stack;
else
e2.stack += '\nWas caused by throwing:\n ' + formatForOutput(e1);
return e2;
}
class Error extends OriginalError {
constructor(msg, chained) {
super(msg);
if (arguments.length > 1)
chainErrors(chained, this);
}
}
return Error;
} else
return OriginalError; // returning the original if we can't chain it
})();
产生:
/path/to/file/script.js:11
throw new Error("Some new Message", e);
^
Error: Some new Message
at testOtherFnc (/path/to/file/script.js:11:15)
at Object.<anonymous> (/path/to/file/script.js:15:1)
at Module._compile (internal/modules/cjs/loader.js:688:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:699:10)
at Module.load (internal/modules/cjs/loader.js:598:32)
at tryModuleLoad (internal/modules/cjs/loader.js:537:12)
at Function.Module._load (internal/modules/cjs/loader.js:529:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:741:12)
at startup (internal/bootstrap/node.js:285:19)
at bootstrapNodeJSCore (internal/bootstrap/node.js:739:3)
Caused by: Error: Some Message
at someErrorThrowingFunction (/path/to/file/script.js:4:11)
at testOtherFnc (/path/to/file/script.js:9:9)
at Object.<anonymous> (/path/to/file/script.js:15:1)
at Module._compile (internal/modules/cjs/loader.js:688:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:699:10)
at Module.load (internal/modules/cjs/loader.js:598:32)
at tryModuleLoad (internal/modules/cjs/loader.js:537:12)
at Function.Module._load (internal/modules/cjs/loader.js:529:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:741:12)
at startup (internal/bootstrap/node.js:285:19)
然后,您可以像在Java中一样:
function someErrorThrowingFunction() {
throw new Error("Some Message");
}
function testOtherFnc() {
try {
someErrorThrowingFunction();
} catch (e) {
throw new Error("Some new Message", e);
}
}
testOtherFnc();
尽管第二个版本带来了一些(其他)问题,但它可能是“更容易”的版本,因为即使引擎不支持链接,您也不需要更改代码,因为您可以为函数(错误构造函数)提供任意多的参数
不管是哪种方式,希望这将是ES2020的一部分。我建议添加原始错误消息。谢谢你的提示!漂亮,小巧,简单-喜欢它!我的版本:module.exports=function(msg,causeE){return new Error(`${causeE.message}:${causeE.stack}\n--------------原因----\n${msg}')}
oo,我喜欢这样。您应该为此制作一个github回购和npm包。我可以看到一些有用的改进(比如消除其他错误和异常之间的重复堆栈跟踪线,以及去掉堆栈的内部TraceError部分)。总有一天我会尝试一下的@BT很高兴你喜欢它:)我已经把它作为npm模块和git回购按照你的要求。我也更新了答案。让我知道如何提高。也许是公关?我不确定你所说的“重复堆栈跟踪线”是什么意思,我的意思是,在大多数情况下,当你捕获一个异常,然后抛出一个相关异常时,原始异常的堆栈跟踪与新创建的异常有许多相同的行,我不确定我是否完全理解你的意思,但我建议将堆栈跟踪的相似部分合并,而不是删除两个相似的部分。所以你仍然可以得到所有的堆栈信息,但你只需要删除重复的部分。老实说,我还没有机会尝试这个,但我接受它作为答案,因为它有所有正确的想法,你经历了麻烦,将它作为一个模块发布,我们都可以从中受益!