我想使用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)
。这也是另一回事
答案 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)。