问题描述
我有一个简单的操作,正在执行一个api调用,结果是一个Observable
,它发出响应:
apiService.getTeam()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Response>() {
...
});
如果几秒钟后没有发出任何物品,我想向用户提供一些反馈。
我知道.timeout()
运算符,但是它会应用于每个项目,因此即使发出了一些项目,在发出最后一个可用项目几秒钟后,超时也会导致错误。
我只想在没有项目发出的情况下使操作超时。 有没有简单的方法可以做到这一点?
1楼
您可以使用timeout
重载来使第一个元素超时,而不使其余元素超时:
Observable.never()
.timeout(() -> Observable.timer(1, TimeUnit.SECONDS), e -> Observable.never())
.toBlocking()
.subscribe(System.out::println, Throwable::printStackTrace);
在这里,第二个参数只是返回一个Observable,它将永远不会发出,因此后续元素不会超时。
2楼
以下代码段可以解决您的问题:
public static void main(String[] args) {
boolean itemEmitted[] = { false };
long identifier = -1l;
Observable.interval(10, TimeUnit.SECONDS)
.mergeWith(Observable.just(identifier).delay(5, TimeUnit.SECONDS))
.map(v -> {
if (!itemEmitted[0] && v == identifier) { // item is not emitted and a timeout occurs
throw new RuntimeException("timeout");
}
itemEmitted[0] = true;
return v;
}).filter(v -> v != identifier).toBlocking()
.subscribe(v -> System.out.println(v));
}
Observable.interval
是您的源Observable
,它发出的项目会与Observable.just
合并在一起,只是带有delay
-其组合类似于timeout
。
map
输出Observable
来检查是否发出了实际项目或是否发生了超时identifier
。
如果超时,则抛出Exception
。
稍后,对输出进行filter
以从发射项目列表中删除标识符。
您可以通过修改初始Observable.interval
的值来使用此代码。