Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在javascript中链接异常(如在java中添加原因)_Java_Javascript_Node.js_Error Handling - Fatal编程技术网

如何在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

是否有标准/最佳实践方法可以在javascript中添加异常原因。在java中,您可以执行以下操作:

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回购按照你的要求。我也更新了答案。让我知道如何提高。也许是公关?我不确定你所说的“重复堆栈跟踪线”是什么意思,我的意思是,在大多数情况下,当你捕获一个异常,然后抛出一个相关异常时,原始异常的堆栈跟踪与新创建的异常有许多相同的行,我不确定我是否完全理解你的意思,但我建议将堆栈跟踪的相似部分合并,而不是删除两个相似的部分。所以你仍然可以得到所有的堆栈信息,但你只需要删除重复的部分。老实说,我还没有机会尝试这个,但我接受它作为答案,因为它有所有正确的想法,你经历了麻烦,将它作为一个模块发布,我们都可以从中受益!