将面向铁路的故障跟踪转换为Rx友好错误 [英] Convert Railway oriented failure track to Rx friendly errors

查看:119
本文介绍了将面向铁路的故障跟踪转换为Rx友好错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用一个将结果作为两个跟踪值(成功和失败)的库.在Observable.map函数主体中,我经常从函数的成功跟踪中得到一个可观察的东西,而我不知道如何来处理它们(在Observable.map正文中).

I'm using a library that takes the results as two-track values (success and failure).In the Observable.map function bodies I often get an observable from success track of a function, and I don't know how to handle them (at Observable.map body).

换句话说,我经常陷入结果看起来像以下情况的情况(当然,这是最简单的情况):

In the other words I often get stuck in situations that the result looks something like the following (of course it's the simplest one):

Rop.Result<IObservable<Rop.Result<IObservable,Messages>,Messages>

一方面,将消息转换回异常并引发异常似乎对我来说是有线的,另一方面,错误处理程序是不纯函数,我宁愿不传递它们.

On one hand, translating messages back to exceptions and raising them seems wired to me, and on the other hand, the error handlers are impure functions and I'd rather not pass them around.

我想知道什么标准和干净的解决方案来处理Observable.map主体上的两轨结果中的故障.

I wonder what is the standard and clean solution to handle the failures from two-track results at the Observable.map body.

更新:示例

这是有史以来最简单的问题示例:

This is the simplest ever sample of the problem :

module problem
open FSharp.Control.Reactive

type Person = {FirstName:string;LastName:string}

let getPersonByLastName lastName =

    let persons =   Observable.toObservable<|seq{
            yield {FirstName="Jhone";LastName="Smith"}
            yield {FirstName="Joe";LastName="Smith"}
            yield {FirstName="Jack";LastName="Smith"}
            }

    Rop.succeed persons

let main =
  let final =
    Observable.single("Smith")
    |>Observable.map(fun lastName -> 
                    let personResults = getPersonByLastName lastName
                    personResults
                    )

  0

在此示例中,表达式的final结果类型为IObservable<Result<IObservable<Person>,ErrorMessage list>>,但我希望它为IObservable<Person>,因为进一步的Observable转换将最终导致非常脏和复杂的表达式.

In this example the final result of the expression is of type IObservable<Result<IObservable<Person>,ErrorMessage list>> but I want it to be IObservable<Person>, because further Observable transformations will end up pretty dirty and complicated expressions.

推荐答案

在最简单的层次上,这里需要的是一种提取并浮出包裹在RopResult中的IObservable的方法.解决方案的一部分已在注释中提到(Observable.bind),另一部分是函数RopResult<IObservable<'a>, 'b> -> IObservable<RopResult<'a,'b>>.

On the simplest level, what you need here is a way to extract and then surface an IObservable that is wrapped in a RopResult. One part of the solution was already mentioned in the comments (Observable.bind), the other is a function RopResult<IObservable<'a>, 'b> -> IObservable<RopResult<'a,'b>>.

要做到这一点,您需要解构RopResult并处理这两种情况.因此,将其放在您陈述的问题中:

To get that, you need to deconstruct the RopResult and handle both the cases. So to put that in context of your stated problem:

Observable.single("Smith")
|>Observable.bind(fun lastName -> 
    match getPersonByLastName lastName with
    | Rop.RopResult.Success (next, msgs) -> 
        next |> Observable.map (fun x -> Rop.RopResult.Success (x, msgs))
    | Rop.RopResult.Failure msgs ->
        Observable.result <| Rop.RopResult.Failure msgs)

这是好的代码吗?我不这么认为.您可以通过使用其他ROP api函数或对绑定主体使用计算表达式来使它更好一些,但这不是重点.

Is this good code though? I don't think so. You could make it slightly better perhaps by using other ROP api functions, or by using a computation expression for the body of the bind here, but that's not the point.

使用Observables的反应式编程和面向铁路的编程"都是有用的工具,只要它们可以捕获并抽象出您要建模的任何计算中涉及的复杂性的某些要素即可.之所以行之有效,是因为它们基于可很好地组合在一起的基元.当您尝试像这样交织"两者时,由于必须自己管理该合成,因此您将放弃其中的一些.

Both reactive programming using Observables, and "railway-oriented programming" are useful tools as long as they can capture and abstract away some element of complexity involved in whatever computation you're modelling. This works because they're build on primitives that compose well together. When you try to "interleave" the two like this, you forfeit some of that as you have to manage that composition yourself.

我会说您最好使用-尤其是因为Observable具有内置的支持.

I would say you're better off using exceptions here - especially since Observables have a built-in support for them.

这篇关于将面向铁路的故障跟踪转换为Rx友好错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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