使用RX的最佳实践-返回一个Observable或接受一个Observer

本文关键字:一个 Observable Observer RX 返回 使用 最佳 | 更新日期: 2023-09-27 18:28:22

使用Reactive Extensions,我可以想出许多方法来对有副作用/IO的操作进行建模,比如订阅聊天室的消息。我可以接受参数(比如聊天室),也可以接受观察员,返回一次性的,即

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

或返回给定参数的Observable,即

Observable<ChatMessage> GetObservableFor(string chatRoom)

当返回Observable时,我还可以在将其设为"热"或"冷"之间进行选择,即在调用我的方法时或在订阅Observable的时候执行实际订阅。此外,我可以使Observable多路复用或不多路复用,即当Observable有多个订阅者时共享相同的底层订阅,或者在每次订阅时发起新的请求

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

使用RX的最佳实践-返回一个Observable或接受一个Observer

返回一个*I*Observable要好得多,因为您可以用其他运算符组合返回的IOobservable。尝试将东西放入自定义的SubscribeTo方法对我来说似乎是个坏主意,因为SubscribeTo没有任何可组合的东西,所以你有点把自己逼到了一个角落。如果您返回IOobservable,那么您可以在以后决定是否要发布/延迟等…,只要您愿意,只需使用IO的现有运算符即可。如果您在SubscribeTo中执行此操作,则已决定,一切都必须承担后果。行为将被封装在SubscribeTo中,这违背了IO的目的。。。明确任何副作用。

我同意另外两个答案。我想进一步补充一些澄清:

  1. 如果你的可观察序列是热的,那么它几乎肯定是共享的。所以,当你谈论热门和共享是不同的东西时,听起来你可能会有一些困惑
  2. 我认为订阅有副作用是可以的。在函数式编程中,大多数关于避免副作用的讨论都是关于管道中的运算符,而不是管道的构造。即不要在Where/Select/Take等操作员中产生副作用。这样做会造成不和谐的体验,并导致不可预测的结果。这妨碍了安全成分,而安全成分是FP的基石
  3. 将参数传递给返回可观察序列的方法是完全可以的!您的示例是一个很好的示例,说明何时进行订阅。其他示例包括订阅频道、端点、会话、计时器等
  4. 避免使用IObservable<T>的自定义实现。这只是一个拒绝。我已经使用Rx超过3年了,根本不需要它。即使使用Subject实现也是罕见的。正如Brad所说,看看Observable.Create来创建序列*

总之,我建议你最终得到一个看起来像这样的界面:

IObservable<ChatMessage> MessagesFor(string chatRoom)

关于共享可观察序列的问题,这在很大程度上是你需要根据自己的需求和架构来决定的。有时,你可能会发现底层传输层会为你做这件事,所以你没有必要对其进行编码。有时,你会发现共享订阅意味着第二个以上的订阅用户可能会错过只在订阅时出现的消息(例如,State Of World)。你可以使用ReplaySubject作为你的MultiCaster来解决这个问题。这引发了其他问题;你准备好为存储ChatMessages承担可能无限的成本了吗?

*披露:链接是我自己的网站

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

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

使多播在第一个订阅时变热,然后在最后一个订阅被丢弃时变冷。