【问题标题】:Lazy compose Observables懒惰编写 Observables
【发布时间】:2018-05-05 07:10:45
【问题描述】:

说我有这个

Observable<A> getA() {
  return Observable.just(new A());
}

Observable<C> getC() {
  // ... some expensive call
  return Observable.just(new C());
}

Observable<B> getB() {
  return getA()
    .map(a -> {
      if (a.someCondition()) {
        final B b = new B();
        b.setSomeFields(...);
        return b;
      }
      if (a.otherCondition()) {
        final B b = new B();
        b.setOtherFields(...);
        return b;
      }
      final B b = new B(...);
      b.setC(getC().toBlocking().single());
      return b;
    });
}

getC() 进行一些昂贵的调用(或有副作用)。我想进行此调用并仅在不满足a.someCondition()a. otherCondition() 时初始化B.c 字段,如上所述。

我将如何重写以摆脱.toBlocking()

我想到的一种方法是压缩getA()getC()

Observable<B> getB() {
  return Observable.zip(getA(), getC(), (a, c) -> Tuple.of(a, c))
    .map(tuple -> {
      final A a = tuple._1;
      final C c = tuple._2;
      if (a.someCondition()) {
        final B b = new B();
        b.setSomeFields(...);
        return b;
      }
      if (a.otherCondition()) {
        final B b = new B();
        b.setOtherFields(...);
        return b;
      }
      final B b = new B(...);
      b.setC(c);
      return b;
    });
}

但这会一直拨打昂贵的电话。当有更复杂的条件或我有超过 2 个 Observables 需要压缩时,也很难阅读。

编辑

@ESala 下面的回答有效,但有时从map 切换到flatMap 需要进行大量更改。下面的解决方案是否也有效?

Observable<B> getB() {
  return getA()
    .map(a -> {
      if (a.someCondition()) {
        final B b = new B();
        b.setSomeFields(...);
        return b;
      }
      if (a.otherCondition()) {
        final B b = new B();
        b.setOtherFields(...);
        return b;
      }
      final B b = new B(...);
      getC().forEach(c -> b.setC(c));
      return b;
    });
}

【问题讨论】:

    标签: java functional-programming rx-java reactive-programming


    【解决方案1】:

    您可以使用flatMap 而不是map,这样可以避免使用toBlocking,并且只在必要时进行昂贵的调用。

    例子:

    Observable<B> getB() {
      return getA()
        .flatMap(a -> {                  // <-- flatMap here
          if (a.someCondition()) {
            final B b = new B();
            b.setSomeFields(...);
            return Observable.just(b);   // <-- wrap in observable
          }
          if (a.otherCondition()) {
            final B b = new B();
            b.setOtherFields(...);
            return Observable.just(b);   // <-- wrap in observable
          }
          return getC().map(c -> {       // <-- expensive call executed
              B b = new B(...);          //     only when necessary
              b.setC(c);
              return b;
          });
        });
    }
    

    更新关于问题中的编辑:

    我不认为切换到flatMap 需要进行大量更改。有具体的例子吗?

    关于您编辑中的替代解决方案:它可以在这种情况下工作,但我不推荐它。

    通过这样做,您正在创建另一个订阅,它不由主要的可观察流管理,通常不应该发生这种情况。 forEach 运算符返回一个 Disposable,它挂在那里!

    它可能导致的一些问题包括:1)如果您取消订阅主 observable,forEach 订阅无论如何都会继续,2)如果您在 getC() 方法中指定调度程序,主要 observable 可以在 @ 之前完成987654332@已完成。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-15
    • 1970-01-01
    • 2022-01-09
    • 2012-06-02
    • 2015-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多