【问题标题】:How should I handle side-effects in RxJava?我应该如何处理 RxJava 中的副作用?
【发布时间】:2019-04-16 18:42:24
【问题描述】:

我有一个 Observable,它发出一个特定的对象 S。这个对象内部有一个对象列表,每个对象都包含一组值。我需要这个数据平面(将所有内部集合展开为一长串平面对象 A),如果它不存在,则将其存储在数据库中,然后将对象 A 的序列减少回具有类似的对象 T结构到起始对象 S,我需要传递它。

我认为在你的函数之外改变状态不是一个好主意,所以把它写成这样一个大的 Observable 转换是不行的(特别是因为在第二个映射中还有一个阻塞的数据库调用):

sObservable
    .map(turnSIntoAFn)     // <-- Actually more complex
    .map(a -> {
         store(a);
         return a;
    })
    .map(turnAIntoTFn)     // <-- Actually more complex
    .subscribe(...);

然后我想我应该将我的副作用限制在订阅者身上。这会让我遇到以下任何一种情况:

  • 将 Observable 转换为 Observable,然后使用将这些 A 放入数据库的订阅者进行订阅。然后查询数据库,在 Observable 中获取 A(MongoDB 的 Rx 驱动程序万岁),将它们转换为 T 并传递(与订阅者一起)

  • 使用源 Observable,同时做两件事:

    1. 与上一步一样,将其转换为 Observable 并将 A 存储在数据库中。
    2. 将 Observable 直接转换为 Observable,乐观地传递它。

目前,第一个选项看起来更有吸引力,尽管它比脏版本和第二个选项需要更多的数据库操作。难道没有更好的方法来做这种事情(对数据做一些有用的事情,然后将其传递)而不会对资源造成更多压力并改变我的功能之外的状态?

【问题讨论】:

  • 第二个map的返回值是否以任何方式依赖外部状态,例如。 G。是从数据库重新读取吗?因为如果不是(我认为不应该),那么您可以改用doOnNext。这清楚地表明,那里发生的事情只是一个副作用,对下面发生的事情没有影响......
  • 我对副作用有同样的疑问。在这种情况下,我可以从obsevable.map(turnSIntoAFn) 获取可观察对象并将其用于订阅存储 a 并创建可观察对象以映射。我不知道这是否是个好主意。

标签: rx-java


【解决方案1】:

您应该考虑使用the do operators - 在本例中为doOnNext()

doOn[Next/Error/Completed] 就像您可以放入序列中的具有副作用的小订阅。这不是转换的一部分(因为他们无法转换数据)。

【讨论】:

    【解决方案2】:

    我更喜欢使用其他运算符,例如concatMap()switchMap()(它们之间的区别是另一个主题)。特别是如果您在某些数据库中有store(a) 操作(例如SQL)。

    doOn[Next/Error/Completed] - 是异步回调,它们最好的用例是一些动作,比如在 UI 进度条上显示/隐藏。

    【讨论】:

      猜你喜欢
      • 2013-09-02
      • 2018-12-27
      • 2014-08-19
      • 2016-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-08
      相关资源
      最近更新 更多