RxJava同步循环

时间:2017-01-25 21:25:15

标签: rx-java

我想使用RxJava在Java中实现async while循环。

更具体地说,这是我的非异步Java代码:

    for (String dataCenter : dataCenters) {
        final Set<Server> serversInDataCenter = getServersInDataCenterSync(dataCenter);
        if (!CollectionUtils.isEmpty(serversInDataCenter)) {
            final Server available = findOneWithSlots(serversInDataCenter);
            if (available != null) {
                return available;
            }
        }
        // if no available server found for current dataCenter, try next
    }
    return null;

上面的代码是从数据中心找到可用的服务器。

由于90%的情况,第一个数据中心将有一台服务器可供检查,我不想提前为所有数据中心提取所有服务器。

现在,假设Set<Server> getServersInDataCenterSync(String dataCenter)方法已更改为异步方法,而是采用回调:void getServersInDataCenter(String dataCenter, AsyncResultHandler<Set<Server>> handler)。这也是另一回事

1 个答案:

答案 0 :(得分:2)

Observable.fromIterable(dataCenters) // emits data center names
    .flatMap(name -> getServersInDataCenter(name), // returns Observable<Server>
        maxConcurrency) // see note below
    .filter(Server::hasSlotsAvailable) // pass through only available ones
    .take(1) // take first one and unsubscribe

在我的示例getServersInDataCenter()中返回Observable<Server>。为了将回调样式方法转换为可观察流,您可以使用以下内容:

Observable<Server> getServersInDataCenter(String name) {
    return Observable.create(emitter ->
        getServersInDataCenterAsync(name, event -> {
            if (event.isError()) 
                emitter.onError(event.getError());
            else {
                emitter.onNext(event.getResultSet()); // emit Set<Server>
                emitter.onComplete();
            }
        })
        .flatMapIterable(set -> set); // flatten Set into individual items
}

使用maxConcurrency参数,您可以限制并发异步请求的数量。如果您在第一个数据中心检查所有服务器之前不想发出第二个请求,请将其设置为1.如果您想在没有多少服务器的情况下加速查找可用服务器,请增加它。您可能还想使用delayErrors参数(请参阅文档here)。