使用Reactive Extensions,我可以想到一些方法来模拟具有副作用/ IO的操作 - 比如订阅来自聊天室的消息。我可以接受参数(比如聊天室)和观察者,返回一个Disposable,即
Disposable SubscribeTo(string chatRoom, Observer<ChatMessage> observer)
或给出参数的Observable,即
Observable<ChatMessage> GetObservableFor(string chatRoom)
当返回一个Observable时,我还可以选择使其成为“热”还是“冷”,即在调用my方法或者观察observable时执行实际订阅。另外,我可以使可观察的多路复用与否,即当Observable有多个用户时共享相同的基础订阅,或者每次订阅时都发起新的请求。
对于订阅带参数的外部事件源的操作,是否有使用RX的最佳实践方法?
答案 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)
我同意其他两个答案。我想进一步补充一些说明:
Where
/ Select
/ Take
等运营商中制造副作用。这样做会产生刺耳的体验并导致不可预测的结果。这可以防止安全成分,这是FP的基石。IObservable<T>
的自定义实现。这只是禁忌。我已经使用Rx超过3年了,而且没有必要。即使使用Subject实现也很少见。正如Brad所说,请期待Observable.Create创建序列。* 总结一下,我建议你最终得到一个如下所示的界面:
IObservable<ChatMessage> MessagesFor(string chatRoom)
关于共享可观察序列的问题,您需要根据自己的要求和架构来决定。有时您可能会发现底层传输层将为您执行此操作,因此您无需对其进行编码。其他时候您可能会发现共享订阅意味着第二个+订阅者可能会错过仅在订阅时发生的消息(例如,State-Of-World)。您可以通过使用ReplaySubject作为MultiCaster来实现此目的。这提出了其他问题;你准备好承担存储ChatMessages的可能无限制的费用吗?
*披露:该链接指向我自己的网站