f# - F#异步中的结果与提高?
问题描述
似乎有两种方法可以在async
工作流中返回错误:raise
和Result
.
let willFailRaise = async {
return raise <| new Exception("oh no!")
}
let willFailResult = async {
return Result.Error "oh no!"
}
对于调用者,处理有点不同:
async {
try
let! x = willFailRaise
// ...
with error ->
System.Console.WriteLine(error)
}
async {
let! maybeX = willFailResult
match maybeX with
| Result.Ok x ->
// ...
| Result.Error error ->
System.Console.WriteLine(error)
}
我的问题是:
- 每种方法的优点/缺点是什么?
- 哪种方法更符合 F# 的习惯?
解决方案
这取决于我们在谈论什么样的错误。基本上分为三种:
- 域错误(例如,用户提供了无效数据、使用此电子邮件的用户已注册等)
- 基础设施错误(例如,您无法连接到另一个微服务或数据库)
- 由程序员的错误引起的恐慌(例如
NullReferenceException
或等等)。StackOverflowException
虽然这两种方法都可以完成工作,但通常您应该关心的应该是使您的代码尽可能地自记录且易于阅读。这意味着以下内容:
- 域错误:绝对选择
Result
. 这些“错误”是意料之中的,它们是您工作流程的一部分。UsingResult
在函数的签名中反映了您的业务规则,这非常有用。 - 基础设施故障:视情况而定。如果您有微服务,那么可能会出现这些故障,并且使用起来可能会更方便
Result
。如果没有 - 去寻找例外。 - 恐慌:绝对
Exception
。首先,您不能用覆盖所有内容Result
,无论哪种方式,您都需要全局异常过滤器。第二件事——如果你试图覆盖所有可能的恐慌——代码会非常快地变成一场令人讨厌的灾难,这将扼杀使用Result
域错误的全部意义。
Async
所以实际上这与C# 互操作无关,它与代码的可读性和可维护性有关。至于C# iterop——别担心,Result
有所有的方法来帮助,比如IsError
等等。但是你总是可以添加一个扩展方法:
[<AutoOpen>]
module Utils =
type Result<'Ok, 'Error> with
member this.Value =
match this with
| Ok v -> v
| Error e -> Exception(e.ToString()) |> raise
推荐阅读
- azure - Azure 隔离计时器触发功能在部署到 Azure 后不起作用
- reactjs - 卡在 Edit src/App.js 并保存以在 heroku 重新加载
- ios - 当我们尝试删除服务器时,如何停止音频会话“outputVolume”观察者崩溃
- python - 尝试打印包含 int 和 str 的列表,但不打印整数
- google-apps-script - 为什么 Google 表格网络应用需要验证会导致“查看、编辑、创建和删除您的所有 Google 表格电子表格”
- jenkins - 从管道脚本解析 Jenkins 轮询日志
- apache-spark - 如何在窗口 10 (HADOOP_HOME) 的单个环境变量中设置两个路径
- android - Android studio 需要为 Mac Monterey 更新
- ios - 如何使用 PickerView 值作为 Timer 倒计时的起始编号
- javascript - 正则表达式忽略文本中间的破折号或连字符