使用RX的最佳做法 - 返回Observable或接受观察者?

时间:2013-08-19 13:16:19

标签: c# system.reactive

使用Reactive Extensions,我可以想到一些方法来模拟具有副作用/ IO的操作 - 比如订阅来自聊天室的消息。我可以接受参数(比如聊天室)和观察者,返回一个Disposable,即

Disposable SubscribeTo(string chatRoom, Observer<ChatMessage> observer)

或给出参数的Observable,即

Observable<ChatMessage> GetObservableFor(string chatRoom)

当返回一个Observable时,我还可以选择使其成为“热”还是“冷”,即在调用my方法或者观察observable时执行实际订阅。另外,我可以使可观察的多路复用与否,即当Observable有多个用户时共享相同的基础订阅,或者每次订阅时都发起新的请求。

对于订阅带参数的外部事件源的操作,是否有使用RX的最佳实践方法?

3 个答案:

答案 0 :(得分:6)

返回* I * Observable要好得多,因为您可以将返回的IObservable与其他运算符组合在一起。尝试将东西放入自定义的SubscribeTo方法对我来说似乎是一个坏主意,因为没有任何关于SubscribeTo的可组合,所以你有点把自己画成一个角落。如果您返回IObservable,那么您可以稍后决定是否要发布/推迟等等...,只需使用现有的IO运算符即可。如果你在SubscribeTo中做到了,那就决定了,所有事情都必须分担后果。这种行为将被包含在SubscribeTo中,这违背了IO的目的......明确任何副作用。

答案 1 :(得分:3)

IObservable有一个名为Subscribe的方法,有大量的重载。您没有理由编写自定义的SubscribeTo方法。这是一种反模式。

var o = ChatRoom.ObservableFor("alt.buddha.short.fat.guy").Publish().RefCount()

在第一个订阅时使多播成为热点,然后在删除最后一个订阅时冷却。

答案 2 :(得分:2)

我同意其他两个答案。我想进一步补充一些说明:

  1. 如果你的可观察序列很热,几乎可以肯定它是共享的。因此,当你谈论Hot和Shared作为不同的东西时,听起来你可能会有些困惑。
  2. 我认为订阅有副作用。在功能编程中,关于避免副作用的大多数讨论都涉及管道中的运算符,而不是管道的构造。即不要在Where / Select / Take等运营商中制造副作用。这样做会产生刺耳的体验并导致不可预测的结果。这可以防止安全成分,这是FP的基石。
  3. 将参数传递给返回可观察序列的方法是完全没问题的!您的样本是何时这样做的一个很好的例子。其他示例包括订阅频道,端点,会话,计时器等......
  4. 避免使用IObservable<T>的自定义实现。这只是禁忌。我已经使用Rx超过3年了,而且没有必要。即使使用Subject实现也很少见。正如Brad所说,请期待Observable.Create创建序列。*
  5. 总结一下,我建议你最终得到一个如下所示的界面:

    IObservable<ChatMessage> MessagesFor(string chatRoom)
    

    关于共享可观察序列的问题,您需要根据自己的要求和架构来决定。有时您可能会发现底层传输层将为您执行此操作,因此您无需对其进行编码。其他时候您可能会发现共享订阅意味着第二个+订阅者可能会错过仅在订阅时发生的消息(例如,State-Of-World)。您可以通过使用ReplaySubject作为MultiCaster来实现此目的。这提出了其他问题;你准备好承担存储ChatMessages的可能无限制的费用吗?

    *披露:该链接指向我自己的网站