我想编写一个通用的错误处理程序,它将捕获在代码的任何实例中故意抛出的自定义错误。

当我抛出新的错误('sample'),如下所示

try {
    throw new Error({'hehe':'haha'});
    // throw new Error('hehe');
} catch(e) {
    alert(e);
    console.log(e);
}

日志在Firefox中显示为错误:[object object],我无法解析该对象。

对于第二次抛出,日志显示为:错误:呵呵

然而当我这样做的时候

try {
    throw ({'hehe':'haha'});
} catch(e) {
    alert(e);
    console.log(e);
}

控制台显示为:对象{hehe="haha"},我可以在其中访问错误属性。

有什么不同?

区别是否如代码中所示?比如字符串会作为字符串传递而对象作为对象但语法会有所不同?

我还没有探索过抛出错误对象…我只抛出了字符串。

除了以上两种方法,还有别的办法吗?


当前回答

你可以把它作为对象抛出

throw ({message: 'This Failed'})

例如在try/catch中

try {
//
} catch(e) {
    console.log(e); //{message: 'This Failed'}
    console.log(e.message); //This Failed
}

或者只是抛出一个字符串错误

throw ('Your error')

try {
//
} catch(e) {
    console.log(e); //Your error
}

throw new Error //only accept a string

其他回答

TLDR

throw new Error('problem')捕获错误发生位置的许多属性。

抛出“问题”则不然

new Error('message')捕获执行堆栈+其他

使用Error对象允许您在抛出错误时捕获执行堆栈。因此,当错误被传递到错误处理树时,这个堆栈快照也会被传递。

因此,在我的代码库中插入throw“test error”会导致:

而throw new Error('test Error ')会导致:

您可以看到本机Error对象在抛出错误时捕获堆栈,并使捕获错误的任何对象都可以使用它。这使我在调试时更容易跟踪问题。

除此之外,它还捕获诸如fileName、lineNumber和columnNumber等属性。

如果您使用堆栈跟踪,则异常跟踪器将为您记录日志

在这种情况下,堆栈将被打印到浏览器控制台,但如果你使用的是Javascript错误记录工具,如Appsignal或Bugsnag,那么堆栈也将在它们中可用。如果你检查错误对象,你可以直接访问堆栈快照:

err = new Error('test')
err.stack

我用来决定使用哪种格式的启发式方法

当我不打算捕获异常时,我使用new Error('problem')

当我抛出一个错误,因为应用程序中发生了一些意想不到的或超出范围的事情,假设本地数据存储损坏了,我可能不想处理它,但我确实想标记它。在本例中,我将使用Error对象,这样我就有了堆栈快照。

通过使用throw new Error('Datastore is corrupt '),更容易追踪到所发生的事情。

当我计划捕获异常时,我使用抛出'problem'

在重新阅读这篇文章时,我认为下一部分需要一些谨慎。通常,非常具体地说明要捕获的错误是一个好主意,否则您可能会捕获您真正想要一直冒泡的东西。一般来说,创建特定的错误类型并捕获特定的错误(或消息字符串)可能更好。这使得你没有预料到的错误浮出水面。”

如果错误是我计划捕获和处理的预期错误,那么我将不会从堆栈快照中得到太多用处。

假设我使用一个http服务,它返回一个500的http代码。我可以将此视为一个错误,我抛出“responseccode =500”,然后随后捕获并处理。

TLDR:它们是等价的Error(x) === new Error(x)。

// this:
const x = Error('I was created using a function call!');
​​​​// has the same functionality as this:
const y = new Error('I was constructed via the "new" keyword!');

来源:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error

throw和throw Error函数是等价的。但是当你捕获它们并将它们序列化到console.log时,它们的序列化方式并不完全相同:

throw 'Parameter is not a number!';
throw new Error('Parameter is not a number!');
throw Error('Parameter is not a number!');

Console.log(e)将产生2个不同的结果:

Parameter is not a number!
Error: Parameter is not a number!
Error: Parameter is not a number!

你可以把它作为对象抛出

throw ({message: 'This Failed'})

例如在try/catch中

try {
//
} catch(e) {
    console.log(e); //{message: 'This Failed'}
    console.log(e.message); //This Failed
}

或者只是抛出一个字符串错误

throw ('Your error')

try {
//
} catch(e) {
    console.log(e); //Your error
}

throw new Error //only accept a string

投掷“我是邪恶的”

Throw将终止进一步的执行并在捕获错误时暴露消息字符串。

尝试{ 投掷“我是邪恶的” console.log("你永远也找不到我",123465) } catch (e) { console.log (e);//我是邪恶的 }

抛出后将永远无法到达控制台,导致终止。


抛出新的错误("I'm Evil")

暴露一个带有两个参数名称和消息的错误事件。它还会终止进一步的执行

尝试{ 抛出新的错误("I'm Evil") console.log("你永远也找不到我",123465) } catch (e) { console.log (e.name e.message);//错误I'm Evil }

抛出错误("I'm Evil")

为了完整起见,这个也可以,虽然技术上不是正确的方法

尝试{ 抛出错误("I'm Evil") console.log("你永远也找不到我",123465) } catch (e) { console.log (e.name e.message);//错误I'm Evil } console.log(typeof(新的错误("hello"))) //对象 console.log(typeof(Error)) //函数

这是相当古老的,但希望任何搜索它的人仍然可以从中学到东西:

首先,在javascript中,我们有一个叫做原始包装器的东西;原语包装器接受原语数据,并通过简单地使用“构造函数模式”以对象格式表示它。不过,在原语包装器中,您可以决定将数据作为对象类型返回,也可以将其作为原语类型返回(在这种情况下,您现在得到了一个让javascript提取原语值的go-ahead命令,在这种情况下,您不使用new关键字)。

总而言之:

throw "My error": this creates an Error object and returns the primitive data extracted from the constructor "this" object. And if you try checking the typeof in the catch block, it tells you its a primitive typeof "string" throw new Error("My error"): this returns you an object where you can access the error value from the message property. What simply happens here is that the "new keyword" constructs a "this" object and assign "{name:"Error",message:"..."}" to it and returns it. And when you try to check the typeof from the catch block, you will see a typeof "object".

注意:在显式地将自定义对象传递给throw的情况下,它的行为就像使用new关键字调用构造函数一样,因此,catch块将返回自定义对象而不是消息属性值。例如:throw {name:"RangeError",message:"range is out of scope",environment:" occurred in testing function"}。

总之,使用任何适合你的东西,你知道你在做什么。但对于我来说,如果我不需要太多的数据,而只是需要错误,那么我就使用原始返回器。