结果与提高F#异步? [英] Result vs raise in F# async?

查看:89
本文介绍了结果与提高F#异步?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

async工作流程中似乎有两种方法可以返回错误:raiseResult.

It seems like there are two ways to return errors in an async workflow: raise and Result.

let willFailRaise = async {
  return raise <| new Exception("oh no!")
}

let willFailResult = async {
  return Result.Error "oh no!"
}

对于呼叫者,处理方式略有不同:

For the caller, the handling is a bit different:

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#?

推荐答案

这取决于我们在谈论哪种错误.基本上有三种:

It depends on what kind of error we are talking about. Basically there are three kinds:

  • 域错误(例如,用户提供的无效数据,使用此电子邮件的用户已注册等)
  • 基础架构错误(例如,您无法连接到另一个微服务或数据库)
  • 由程序员的错误引起的恐慌(例如NullReferenceExceptionStackOverflowException等).
  • Domain errors (e.g. user provided invalid data, user with this email is already registered, etc.)
  • Infrastructure errors (e.g you can't connect to another microservice or DB)
  • Panics (e.g. NullReferenceExceptionor StackOverflowException etc.), which are caused by programmers' mistakes.

尽管两种方法都能完成工作,但是通常您需要考虑的是使代码尽可能具有自记录性并易于阅读.这意味着:

While both approaches can get the job done, usually your concern should be to make your code as self-documented and easy-to-read as possible. Which means the following:

  • 域错误:肯定适用于Result.这些错误"是预期的,它们是您工作流程的一部分.使用Result可以在功能的签名中反映您的业务规则,这非常有用.
  • 基础结构故障:.如果您有微服务,则可能是那些失败的预料,并且使用Result可能会更方便.如果不是,请寻求例外.
  • Panics:肯定是Exception.首先,您无法使用Result覆盖所有内容,您将需要使用两种方法中的全局异常过滤器.第二件事-如果您试图掩盖所有可能的紧急情况-代码将很快变得令人讨厌,这将使使用Result处理域错误的全部事情丧命.
  • Domain errors: definitely go for Result. Those "errors" are expected, they are part of your workflow. Using Result reflects your business rules in function's signature, which is very useful.
  • Infrastructure failures: it depends. If you have microservices, then probably those failures are expected and maybe it would be more convenient to use Result. If not -- go for exceptions.
  • Panics: definitely Exception. First of all, you can't cover everything with Result, you gonna need global exception filter either way. Second thing -- if you try to cover all possible panics - code becomes a nasty disaster extremely fast, that will kill the whole point of using Result for domain errors.

因此,这实际上与Async或C#互操作无关,它与代码的可读性和可维护性有关. 至于C#iterop,请放心,Result具有所有帮助方法,例如IsError等.但您始终可以添加扩展方法:

So really this has nothing to do with Async or C# interop, it's about code readability and maintainability. As for C# iterop -- don't worry, Result has all the methods to help, like IsError and so on. But you can always add an extension method:

[<AutoOpen>] module Utils = type Result<'Ok, 'Error> with member this.Value = match this with | Ok v -> v | Error e -> Exception(e.ToString()) |> raise

[<AutoOpen>] module Utils = type Result<'Ok, 'Error> with member this.Value = match this with | Ok v -> v | Error e -> Exception(e.ToString()) |> raise

这篇关于结果与提高F#异步?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆