ConnectableObservable与flatMap()自引用?

时间:2015-11-09 15:32:10

标签: java reactive-programming rx-java

我对ConnectableObservable的用例感到好奇,并认为从寒冷的可观测量(如数据库查询)转换昂贵的排放可能会有所帮助,并将它们作为热点发出。这样可以避免昂贵的重放,并且会将一组排放推送给所有运营商和订户。

经过一些思考实验后,我有些担心flatMaps中的自引用会引起问题。

例如,假设我通过ConnectableObservable发出值1到10。但我flatMap()每个值都是所有值的总和,然后减去当前值。

    ConnectableObservable<Integer> source = Observable.range(1,10)
            .doOnNext(System.out::println)
            .publish();

    source.flatMap(i -> source.reduce(0,(x,y) -> x + y).map(sum -> sum - i))
            .subscribe(sum -> System.out.println("SUM - i: " + sum));

    source.connect();

我希望我能得到这个输出。

1
2
3
4
5
6
7
8
9
10
SUM - i: 54
SUM - i: 53
SUM - i: 52
SUM - i: 51
SUM - i: 50
SUM - i: 49
SUM - i: 48
SUM - i: 47
SUM - i: 46
SUM - i: 45

但我得到了这个。

1
2
3
4
5
6
7
8
9
10
SUM - i: 53
SUM - i: 50
SUM - i: 46
SUM - i: 41
SUM - i: 35
SUM - i: 28
SUM - i: 20
SUM - i: 11
SUM - i: 1
SUM - i: -10

正如我所担心的那样,flatMap()看起来需要重放值,因为它无法处理源的热顺序性质。因此,如果我使用cache()运算符,那么一切正常,因为每个flatMap()运算符都会重放缓存的值。

    Observable<Integer> source = Observable.range(1,10)
            .doOnNext(System.out::println)
            .cache();

    source.flatMap(i -> source.reduce(0,(x,y) -> x + y).map(sum -> sum - i))
            .subscribe(sum -> System.out.println("SUM - i: " + sum));

这是我的问题:

  1. ConnectableObservable进程究竟发生了什么?它看起来是确定性的,那么它是如何产生这些价值的呢?

  2. 在任何使用它的运营商中ConnectableObervable可能对自我引用有危险吗?在这种情况下,cache()应该是热门运营商吗?

1 个答案:

答案 0 :(得分:2)

  

这个ConnectableObservable流程究竟发生了什么?它看起来是确定性的,那么它是如何产生这些价值的呢?

这种设置是非直观的,但是发生的事情是内部总和在它们各自的起始值被创建之前不存在,并且它们中的每一个在它们创建之后只看到原始序列一个元素。例如,对于1,内部总和将仅从2到10开始事件。

  

在使用ConnectableObervable的任何运算符中,ConnectableObervable可能对自引用有危险吗?在这种情况下,cache()应该是热门运营商吗?

问题不在于ConnectableObservable,而是publish对时间敏感且Subscriber敏感:谁在那里接收事件,谁不在那里不会得到任何追溯