带有vertx的RxJava:不能有多个订阅异常

时间:2016-05-18 16:08:38

标签: java system.reactive rx-java vert.x

我正在尝试使用RxJava避免vertx回调地狱。 但我有“rx.exceptions.OnErrorNotImplementedException: Cannot have multiple subscriptions”。这有什么不对?

public class ShouldBeBetterSetter extends AbstractVerticle {
    @Override
    public void start(Future<Void> startFuture) throws Exception {
        Func1<AsyncMap<String,Long>, Observable<Void>> obtainAndPutValueToMap = stringLongAsyncMap -> {
            Long value = System.currentTimeMillis();
            return stringLongAsyncMap.putObservable("timestamp", value)
                .doOnError(Throwable::printStackTrace)
                .doOnNext(aVoid -> System.out.println("succesfully putted"));
        };

        Observable<AsyncMap<String,Long>> clusteredMapObservable =
                vertx.sharedData().<String,Long>getClusterWideMapObservable("mymap")
                        .doOnError(Throwable::printStackTrace);

        vertx.periodicStream(3000).toObservable()
                .flatMap(l-> clusteredMapObservable.flatMap(obtainAndPutValueToMap))
                .forEach(o -> {
                    System.out.println("just printing.");
                });
    }
}

可以在此处找到工作Verticle(没有Rx): https://gist.github.com/IvanZelenskyy/9d50de8980b7bdf1e959e19593f7ce4a

2 个答案:

答案 0 :(得分:1)

vertx.sharedData()。getClusterWideMapObservable(“mymap”)返回observable,它仅支持单个订阅者 - 因此异常。值得一试的一个解决方案是:

Observable<AsyncMap<String,Long>> clusteredMapObservable =
            Observable.defer(
            () -> vertx.sharedData().<String,Long>getClusterWideMapObservable("mymap")
 );

这样每次调用clusteredMapObservable.flatMap()时,它都会订阅Observable.defer()返回的新的observable。

修改

如果可以使用相同的AsyncMap,正如@Ivan Zelenskyy指出的那样,解决方案可以

Observable<AsyncMap<String,Long>> clusteredMapObservable =   
vertx.sharedData().<String,Long>getClusterWideMapObservable("mymap").cache()

答案 1 :(得分:1)

发生的事情是,在每次定期发布时,foreach都会重新订阅您在上面定义的clusteredMapObservable变量。

要解决此问题,只需将来电定位于定期信息流vertx.sharedData().<String,Long>getClusterWideMapObservable("mymap")内的flatmap即可。

这样的事情:

vertx.periodicStream(3000).toObservable()
                .flatMap(l-> vertx.sharedData().<String,Long>getClusterWideMapObservable("mymap")
                        .doOnError(Throwable::printStackTrace)
                        .flatMap(obtainAndPutValueToMap))
                .forEach(o -> {
                    System.out.println("just printing.");
                });

更新

如果你不喜欢lambda的labmda,那就不要了。这是一个没有

的更新
vertx.periodicStream(3000).toObservable()
                    .flatMap(l-> {
                        return vertx.sharedData().<String,Long>getClusterWideMapObservable("mymap");
                    })
                    .doOnError(Throwable::printStackTrace)
                    .flatMap(obtainAndPutValueToMap)
                    .forEach(o -> {
                        System.out.println("just printing.");
                    });

PS - 您对.flatMap(obtainAndPutValueToMap))的呼叫也是lambda中的lambda - 您只是将其移动到一个函数中。