如何使用F#的rx扩展从简单值创建可观测值?
目前,我有一个函数,从外部接收原始数据,对其进行处理,并将其发送到回调:如何使用F#的rx扩展从简单值创建可观测值?,f#,rx.net,F#,Rx.net,目前,我有一个函数,从外部接收原始数据,对其进行处理,并将其发送到回调: let处理回调数据= 让数据=原始数据//转换为实际数据。。。。 回调数据 回调是一个函数'T->unit。具体地说,在我的例子中,它是MailboxProcessor的Post功能(被称为processmailbox.Post rawData) process函数被调用多次,每次我将处理后的数据推送到邮箱队列中。到目前为止还不错 现在,我想通过使用FSharp的rx扩展(FSharp.Control.Reactive)
let处理回调数据=
让数据=原始数据//转换为实际数据。。。。
回调数据
回调是一个函数'T->unit
。具体地说,在我的例子中,它是MailboxProcessor的Post
功能(被称为processmailbox.Post rawData
)
process函数被调用多次,每次我将处理后的数据推送到邮箱队列中。到目前为止还不错
现在,我想通过使用FSharp的rx扩展(FSharp.Control.Reactive),以一种可以将处理后的数据发布给各种消费者的方式来更改此代码。这意味着回调
将是一个可观察的函数,或者是一个发布给订阅者的函数。我该怎么做
我找到了两个选择:
进程
函数。如果可能的话,我希望避免创建类
主题.behavior
。这正是我想要的,只是它需要一个初始状态,在这种情况下,这个初始状态在语义上没有意义,而且显然主题是不受欢迎的(来自ReactiveX站点的链接)
从函数式编程的角度来看,哪种方法更好?有更好的方法吗?这里有一个想法:可以使用对象表达式实现
IObservable
,而无需显式类的开销:
let createObservable subscribe =
{
new IObservable<_> with
member __.Subscribe(observer) =
subscribe observer
}
让createObservable订阅=
{
新IObservable与
成员订阅(观察员)=
订阅观察员
}
要使用它,请指定类型为
IObserver->IDisposable
的subscribe
函数。不需要上课。明白了。Fsharp reactive提供模块Fsharp.Control.reactive.Builders
中的关键字observe
。这允许您创建临时观察:
open FSharp.Control.Reactive.Builders
//In my real case, "initialData" is a byte stream and
//at each step I read a few bytes off of it
let Process initialData =
let rec loop data =
observe {
match data with
| x :: xs ->
yield x
yield! loop xs
| [] -> ()
}
loop initialData
let obs = Process ([1;2;3;4;5])
obs.Subscribe(fun d -> printfn "Consumer A: %A" d) |> ignore
obs.Subscribe(fun d -> printfn "Consumer B: %A" d) |> ignore
Threading.Thread.Sleep 1000
obs.Subscribe(fun d -> printfn "Late consumer: %A" d) |> ignore
重要的是要注意,这会创建一个冷的可观察对象,因此已故的使用者会接收所有事件。使用
observe{..}
计算生成器可以工作,但是FSharp.Control.Reactive
库中有一个函数可以执行相同的操作:
open FSharp.Control.Reactive
let obs = Observable.ofSeq [1;2;3;4;5]
如果我使用的是observe{..}
computation builder,我还将使用它支持for
循环这一事实,这使您的代码更加简单:
let Process initialData = observe {
for x in initialData do yield x }
我在回答中使用了一个序列来举例说明,但在我的实际用例中,数据来自网络流。在这种情况下,我想我必须使用
观察。很高兴知道!这可能不是一个好主意。用正确的Rx语义实现一个observable是很困难的,而且总是建议使用Rx的内置功能。你可能是对的,但这就是为什么我不喜欢反应式范例。太神奇了。这更多的是让并发代码安全地编写,这需要大量的检查和平衡——Rx作为monad抽象出线程和并发。