使用 Facebook 的不变量 vs if throw
Using Facebook's invariant vs if throw
我一直在查看各种 Node.js 项目的源代码,我注意到有些人使用 invariant。据我了解,invariant
是一种工具,可让您在代码中放置断言,并根据需要引发错误。
问题:
您什么时候更喜欢使用 invariant
与传统方式抛出错误?
// Using invariant
function doSomething(a, b) {
invariant(a > b, 'A should be greater than B');
}
// If throw
function doSomething(a, b) {
if(a <= b) {
throw new Error('A should be greater than B');
}
}
有几个原因:
- 当你想堆叠它们时更容易阅读。例如,如果您有 3 个要验证的先决条件,您总是会看到
invariant(x ...
,并且很容易看出正在检查的内容:
function f(xs, x) {
// all the invariants are lined up, one after another
invariant(xs.type == x.type, "adding an element with the same type");
invariant(xs.length != LIST_MAX_SIZE, "the list isn't full");
invariant(fitting(x), "x is fitting right in the list");
}
与通常的抛出方法比较:
function f(xs, x) {
if (xs.type != x.type)
throw new Error("adding an element with the same type");
if (xs.length == LIST_MAX_SIZE)
throw new Error("the list isn't full");
if (!fitting(x))
throw new Error("x is fitting right in the list");
}
它可以很容易地在发布版本中消除它。
通常您希望在 dev/test 中检查先决条件,但不希望它们在发布时因为它们会很慢。
如果你有这样一个 invariant
函数,你可以使用像 babel(或其他工具)这样的工具从生产构建中删除这些调用
(这有点像D的做法)
zertosh/invariant
允许添加 code guards
如自述文件中所述,它是一种在开发中提供描述性错误但在生产中提供一般性错误的方法。
然而,它是某些内部 facebook 系统的复制品,而且 imo 的文档记录很糟糕,也没有得到维护。可怕的是4.4M的用途:thinking:
- 什么都不会开箱即用
- 如果您没有构建工具以某种方式删除生产中的消息,您仍然会遇到原始错误
- node 中的用法是 ssr/react 原生的,或者在 "we have less lines" 之外无用
- 它使用
error.framesToPop
这也是 facebook 的东西
参见:https://github.com/zertosh/invariant/issues?q=is%3Aissue
注意:
更好的方法是等待 es 提议 throw inline
并实际执行
cond || throw x
cond ?? throw x
如果 cond 在浏览器中包含一个虚假的 var env,那么无论如何都不会评估和删除错误
在 TypeScript 项目中的实用性
...添加到以前的答案中,使其更易于阅读、代码行更少、从开发版本中剥离:
如果您使用的是 typescript,则可以使用它来帮助缩小类型范围 + 获得开发时间反馈。
想象一下下面的场景:
我们正在从 node/js 中的文件系统中读取,类型系统不知道那里有什么,所以我们需要运行时检查,为此我们需要一个不变的方法来使运行时检查变得如此简单。
注:
- Facebook 有一个现代流行的
invariant
包,名为 tiny-invariant
,我建议将其称为 tiny-variant
:https://github.com/alexreardon/tiny-invariant
我一直在查看各种 Node.js 项目的源代码,我注意到有些人使用 invariant。据我了解,invariant
是一种工具,可让您在代码中放置断言,并根据需要引发错误。
问题:
您什么时候更喜欢使用 invariant
与传统方式抛出错误?
// Using invariant
function doSomething(a, b) {
invariant(a > b, 'A should be greater than B');
}
// If throw
function doSomething(a, b) {
if(a <= b) {
throw new Error('A should be greater than B');
}
}
有几个原因:
- 当你想堆叠它们时更容易阅读。例如,如果您有 3 个要验证的先决条件,您总是会看到
invariant(x ...
,并且很容易看出正在检查的内容:
function f(xs, x) {
// all the invariants are lined up, one after another
invariant(xs.type == x.type, "adding an element with the same type");
invariant(xs.length != LIST_MAX_SIZE, "the list isn't full");
invariant(fitting(x), "x is fitting right in the list");
}
与通常的抛出方法比较:
function f(xs, x) {
if (xs.type != x.type)
throw new Error("adding an element with the same type");
if (xs.length == LIST_MAX_SIZE)
throw new Error("the list isn't full");
if (!fitting(x))
throw new Error("x is fitting right in the list");
}
它可以很容易地在发布版本中消除它。
通常您希望在 dev/test 中检查先决条件,但不希望它们在发布时因为它们会很慢。 如果你有这样一个
invariant
函数,你可以使用像 babel(或其他工具)这样的工具从生产构建中删除这些调用 (这有点像D的做法)
zertosh/invariant
允许添加 code guards
如自述文件中所述,它是一种在开发中提供描述性错误但在生产中提供一般性错误的方法。
然而,它是某些内部 facebook 系统的复制品,而且 imo 的文档记录很糟糕,也没有得到维护。可怕的是4.4M的用途:thinking:
- 什么都不会开箱即用
- 如果您没有构建工具以某种方式删除生产中的消息,您仍然会遇到原始错误
- node 中的用法是 ssr/react 原生的,或者在 "we have less lines" 之外无用
- 它使用
error.framesToPop
这也是 facebook 的东西
参见:https://github.com/zertosh/invariant/issues?q=is%3Aissue
注意:
更好的方法是等待 es 提议 throw inline
并实际执行
cond || throw x
cond ?? throw x
如果 cond 在浏览器中包含一个虚假的 var env,那么无论如何都不会评估和删除错误
在 TypeScript 项目中的实用性
...添加到以前的答案中,使其更易于阅读、代码行更少、从开发版本中剥离:
如果您使用的是 typescript,则可以使用它来帮助缩小类型范围 + 获得开发时间反馈。
想象一下下面的场景: 我们正在从 node/js 中的文件系统中读取,类型系统不知道那里有什么,所以我们需要运行时检查,为此我们需要一个不变的方法来使运行时检查变得如此简单。
注:
- Facebook 有一个现代流行的
invariant
包,名为tiny-invariant
,我建议将其称为tiny-variant
:https://github.com/alexreardon/tiny-invariant