Observable vs FSharpx asyncSeq

时间:2014-01-11 18:25:01

标签: twitter f# tweetinvi

我有以下推文流类。它有TweetReceived事件,可以与我系统的其他组件一起使用。

它似乎工作正常,但我觉得它比它应该更复杂。

是否有任何工具可以为我提供此功能而无需自己实施mbox /事件机制?

您还建议使用asyncSeq而不是IObservable吗?

谢谢!

type TweetStream ( cfg:oauth.Config) =
    let token = TwitterToken.Token (cfg.accessToken,
                                    cfg.accessTokenSecret,
                                    cfg.appKey, 
                                    cfg.appSecret)

    let stream = new SimpleStream("https://stream.twitter.com/1.1/statuses/sample.json")

    let event = new Event<_>()

    let agent = MailboxProcessor.Start(fun (mbox) ->
        let rec loop () =
            async {
                let! msg = mbox.Receive()
                do event.Trigger(msg)
                return! loop()
            }
        loop ()) 

    member x.TweetReceived = event.Publish

    member x.Start () =
        Task.Factory.StartNew(fun () -> stream.StartStream(token, agent.Post))
        |> ignore

    member x.Stop = stream.StopStream

更新: 感谢Thomas对第二个问题的快速(一如既往)回答。

我的第一个问题可能有点不清楚所以我重构了代码以使AgentEvent类可见,我重新解释了第一个问题:有没有办法在AgentEvent中更容易地实现逻辑?这个逻辑是否已经在某个地方实现了?

我问这个是因为它感觉像是一种常见的使用模式。

type AgentEvent<'t>()=
    let event = new Event<'t>()

    let agent = MailboxProcessor.Start(fun (mbox) ->
        let rec loop () =
            async {
                let! msg = mbox.Receive()
                do event.Trigger(msg)
                return! loop()
            }
        loop ()) 
    member x.Event = event.Publish
    member x.Post = agent.Post

type TweetStream ( cfg:oauth.Config) =
    let token = TwitterToken.Token (cfg.accessToken,
                                    cfg.accessTokenSecret,
                                    cfg.appKey, 
                                    cfg.appSecret)

    let stream = new SimpleStream("https://stream.twitter.com/1.1/statuses/sample.json")

    let agentEvent = AgentEvent()

    member x.TweetReceived = agentEvent.Event

    member x.Start () =
        Task.Factory.StartNew(fun () -> stream.StartStream(token, agentEvent.Post))
        |> ignore

    member x.Stop = stream.StopStream

1 个答案:

答案 0 :(得分:3)

我认为IObservable是发布事件的正确抽象。至于处理它们,我会使用Reactive Extensions或F#Agents(MailboxProcessor),具体取决于你想要做什么。

请注意,F#会自动将事件表示为IObservable值(实际为IEvent,但这是从observable继承的),因此您可以直接在TweetReceived上使用Reactive Extensions。

什么是正确的代表?

  • asyncSeq的要点是,它可以让您控制数据生成的速度 - 就像async一样,您必须启动它才能真正完成工作并获得一个值 - 所以如果你可以开始一些操作(例如下载下几个字节)以获得下一个值,这很有用

  • IObservable在您无法控制数据源时非常有用 - 当它只是不断产生值并且您无法暂停时 - 这似乎更适合推文。

    < / LI>

至于处理,我认为当Reactive Extensions已经实现了您需要的操作时,它们很不错。当您需要编写一些自定义逻辑(在Rx中不易表达)时,使用Agent是编写类似Rx函数的好方法。