- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我知道这是重复的,但这里的答案根本不让我满意:
JS library best practice: Return undefined or throw error on bad function input?
我想谈谈一些已被指出的事情以及我仍不清楚的事情。
首先,我想举一个例子,我个人宁愿抛出一个错误然后返回未定义的。
function sum(a, b)
假设消费者传递了一个字符串,因为他传递了一个输入框的直接值,而最终用户输入的不是数字。
如果我作为 sum
的作者在字符串输入时返回了 undefined,那么即使开发人员在某个时候输入了一个字符串,也不会发生任何事情,他也不会在意,就像那样什么是可以预期的。但在这种情况下,如果我抛出一个错误,开发人员会意识到这实际上是一个必须处理的边缘情况,因为毕竟,没有人希望他们的程序出现错误。
那么基本上,为什么不通过实际抛出错误让开发人员了解边缘情况呢?
这是对上面提到的问题的评论,这几乎正是我要问的,但还没有人回答:
"But since it takes 1 extra min for me to throw an error instead of dying silently, won't that save hours in debugging time for those who didn't take the time to read the docs?"
上面接受的答案中的另一点:
"Catching an exception is a lot slower than testing a return value so if an error is a common occurrence, then exceptions will be a lot slower."
我能想到的唯一适用于此 qoute 的情况是 I/O 或网络内容,其中输入始终采用正确的格式,但例如不存在具有该 ID 的用户。
在这种情况下,我理解为什么抛出错误会减慢进程。但同样,一个仅由纯同步函数组成的数学库又如何呢?
检查输入而不是检查输出不是更聪明吗? (确保输入有效,而不是运行函数并检查是否返回 undefined)
我的很多困惑实际上源于类型检查,因为我确实来自 C# 世界,并且认为库应该按照预期的方式使用,而不是仁慈地工作。
最佳答案
我认为对于 OO 语言来说,返回 null 是很常见的,尽管这是不好的做法,null 的发明者将其称为 billion dollar mistake .
函数式语言甚至在 OO 出现之前就通过 Maybe 类型解决了这个问题。
在编写函数时,您可以使用包含成功或失败的 Maybe 变体,Scott Wlaschin 将其称为 railway orientated programming而 Promises 是一种面向铁路的编程。
在 OO 中使用 Maybe 的问题是你没有 union types .在 F# 中,您的代码将如下所示:
let x =
// 9/0 throws so divideBy returns None the caller of divideBy can
//decide what to do this this.
match (divideBy 9 0) with
| Some result -> //process result
| None -> //handle this case
在 F# 中匹配某些内容时,如果您忘记了大小写(未处理 None
),则会出现编译时 错误。在 OO 中,您不会,并且会遇到运行时错误或悄悄失败。当您尝试访问可空类型时,C# 中的改进可能会伴随编译器警告您,但这只会处理 if not null
,它不会强制您提供 else。
所以在 JavaScript 中,我会建议使用 Promises 或返回结果对象。 Promises 原生于现代浏览器和 nodejs。在浏览器中,当您不处理失败的 promise 时,它会在控制台中对您大喊大叫(控制台中的错误和源代码中未捕获的拒绝中断)。将来;对于 Node ;它会导致您的进程像未处理的异常一样停止。
//example with promises
const processNumber = compose([
//assuming divideBy returns a promise that is rejected when dividing by zero
divideBy(9)
,plus(1)
,minus(2)
,toString
])
// 9/0 returns rejected promise so plus,minus and toString are never executed
processNumber(0)
.then(
success => //do something with the success value
,fail => //do something with the failure
);
//example of result type:
const Success = {}
,Failure = {}
,result = (type) => (value) =>
(type === Failure)
//Failure type should throw when trying to get a value out of it
? Object.create({type:type,error:value}, {
value: {
configurable: false,
get: function() {
throw "Cannot get value from Failure type"
}
}
})
: ({
type:type
,value:value
})
;
//convert a function (T->T) to (result T->result T)
const lift = fn => arg => {
//do not call funcion if argument is of type Failure
if(arg.type === Failure){
return arg;
}
try {
const r = fn(arg.value);
//return a success result
return result(Success)(r);
} catch (e) {
//return a failure result
return result(Failure)(e);
}
};
//takes a result and returns a result
const processNumber = compose(
[
//assuming divideBy throws error when dividing by zero
divideBy(9)
,plus(1)
,minus(2)
,toString
].map( //lift (T->T) to (result T -> result T)
x => lift(x)
)
);
const r = processNumber(result(Success)(0));//returns result of type Failure
if(r.type === Failure){
//handle failure
} else {
//handle r.value
}
您可以只返回 null 或抛出,但越来越多的 OO 人开始意识到那是 not the best way处理事情。抛出是一种副作用,因此会使函数变得不纯(函数越不纯,维护代码就越难)。
Null 不是反射(reflect)可能失败的函数的好类型。您不知道为什么它未能返回预期的类型,现在必须对原因做出假设,在代码中做出假设会使您的代码更难维护。
关于javascript - 在无效函数输入时返回未定义或抛出错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47296984/
我有一个接受以下参数的函数: int setvalue(void (*)(void *)); 为了满足参数:void (*)(void *),我创建了这样一个函数: static void *
我有以下代码: typedef void VOID; int f(void); int g(VOID); 在 C 中编译得很好(在 Fedora 10 上使用 gcc 4.3.2)。与 C++ 编译的
这个问题已经有答案了: Is f(void) deprecated in modern C and C++? [duplicate] (6 个回答) 已关闭 7 年前。 B.A.T.M.A.N./A.
我在 ASP.NET Core 3.1 项目上有以下 Identity Server 4 配置: services .AddIdentityServer(y => { y.Events.R
我们有一个 O365 租户,一切都是开箱即用的。租户放置在德国云中,而不是全局 (office.de) 中。我们还开发了一个 Office 插件,使用 OAuth 2.0 授权访问共享点。首先,我们向
我有一个如下所示的路由 routes.MapRoute( name: "Default", url: "{controller}/{action}/{i
我正在尝试使用 OAuth2.0 访问 google 文档。我已经从 Google API 控制台获取了客户端 ID 和 key 。但是当我运行这段代码时,我收到了异常。如果我遗漏了什么,有人可以建议
此代码有效: let mut b: Vec = Vec::with_capacity(a.len()); for val in a.iter() { b.push(val); } 此代码不起作
使用 client_credintials 授权类型请求 EWS oauth2 v2.0 的访问 token 时出现错误。 https://login.microsoftonline.com/tena
我通过 Java 应用程序使用 Google 电子表格时遇到了问题。我创建了应用程序,该应用程序运行了 1 年多,没有任何问题,我什至在 Create Spreadsheet using Google
如何创建 匹配所有无效 Base64 字符的正则表达式?我在堆栈上找到了 [^a-zA-Z0-9+/=\n\r].*$ 但是当我尝试时我得到了带有 - 符号的结果字符串.我根本不知道正则表达式,任何人
我从 Gitlab CI/CD Pipelines 获得错误信息:yaml invalid。问题是由 .gitlab-ci.yml 脚本的第五行引起的: - 'ssh deployer@gita
我有 3 个数据源,设置如下: @Configuration @Component public class DataSourceConfig { @Bean("foo") @Conf
你好,我想用bulkCreate ex 插入数据: [ { "typeId": 5, "devEui": "0094E796CBFCFEF9", "application_name": "Pressu
UIApplicationExitsOnSuspend 不会强制我的应用程序退出。我已经清理过目标、删除了应用程序、重建并重新安装了很多次。 我确实需要退出我的应用程序。 最佳答案 您是否链接了 SD
在 iPhone 配置门户上,显示我的 iPhone 团队配置配置文件无效。有一个“由 Xcode 管理”文本。 “续订”按钮被禁用。 我该如何解决这个问题?谢谢 最佳答案 使用 Xcode 3.2.
好的,所以今天我用我们的“实时”数据库中的新信息更新了我的数据库……从那时起,我的一个表格就出现了问题。如果您需要任何代码,请告诉我,我将对其进行编辑并发布所需的代码... 我有一个报告表格,其中有一
我有一个结构体,其中有一个元素表示为 void (*func)(); 我知道 void 指针通常用于函数指针,但我似乎无法定义该函数。我不断收到取消引用指向不完整类型的指针。我用谷歌搜索了一下但没有结
我正在尝试使用 Coldfusion 9 从 ning 网络获取凭证,所以首先这是测试 api 的 curl 语法: curl -k https://external.ningapis.com/xn/
这个问题已经有答案了: Does C have references? (2 个回答) 已关闭 4 年前。 我正在学习 C 语言引用,这是我的代码: #include int main(void)
我是一名优秀的程序员,十分优秀!