我必须连续几次调用一个外部API方法,直到我要么用完了尝试,要么得到肯定的回复。如果我没有尝试,我仍然希望使用(用于记录/诊断目的)最新的不成功响应。目前我这样做:
class SimpleWrapper<T> {
private T data;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
SimpleWrapper<String> state = new SimpleWrapper<>();
Observable<Response> getLogObservable = Observable.interval(checkInterval, TimeUnit.SECONDS)
.take(checkCount)
.flatMap(ignored -> api.check())
.doOnNext(response -> {
logger.info("Check response: {}", response.getMessage());
state.setData(response.getMessage());
})
.firstOrDefault(null, HubLogsApiResponse::isSuccess)
.flatMap(response -> {
if (response == null) {
return Observable.error(new RuntimeException(String.format("Last call to check was unsuccessful: %s", state.getData())));
} else {
return Observable.just(response);
}
})
这很丑,需要我使用副作用,但我不知道如何才能实现这一点。
有任何建议吗?
答案 0 :(得分:0)
问题:发出一系列请求,并返回第一个成功请求,或者返回最后一个请求。
如果我们引入Pair
,我们可以将interval
生成的计数与API请求结合起来。然后,可以在不设置全局变量的情况下检查终止条件。
Observable<Response> getLogObservable =
Observable.interval(checkInterval, TimeUnit.SECONDS)
.flatMap(requestNumber -> api.check()
.map(response ->
new Pair(requestNumber+1, response))
.flatMap(pair -> mapResponse( pair ) )
.take( 1 );
Observable<Response> mapResponse( Pair<Long, Response> response ) {
if ( response.getSecond().isSuccess() ) {
return Observable.just( response.getSecond() );
}
if ( response.getFirst() >= checkCount ) {
Observable.error(
new RuntimeException(String.format("Last call to check was unsuccessful: %s",
pair.getSecond().getData())));
}
return Observable.empty();
}
mapResponse
只会在计数器运行过程中产生包含最新响应的错误。否则,它返回成功的响应或空的observable。