RxJava仅检查具有超时的第一个响应项

时间:2016-09-03 07:19:54

标签: java rx-java reactive-programming

我看到ReactiveX(RxJava)有一个运算符timeout,它将应用于订阅流中的每个项目。但我只想检查超时的第一个响应,而不关心以下响应的超时。如何使用RxJava的运算符优雅地实现此要求?

5 个答案:

答案 0 :(得分:3)

这是一种更实用的方法。它在Scala中,但应转录为Java:

val myTimeout : Observable[Nothing] = Observable timer (10 seconds) flatMap (_ => Observable error new TimeoutException("I timed out!"))

myStream amb myTimeout

amb运算符返回首先发出的observable的值。

答案 1 :(得分:2)

一种方法如下:

Observable<Response> respStream = respStream();
ConnectableObservable<Response> sharedRespStream = respStream.publish();

Observable<String> first = sharedRespStream.first().timeout(2, TimeUnit.SECONDS);
Observable<String> rest = sharedRespStream.skip(1);
Observable<String> result = first.mergeWith(rest);

sharedRespStream.connect();

result.subscribe(response -> handleResponse(response), error -> handleError(error));

代码是自我解释:共享响应以避免重复请求,对发出的第一项应用超时,并将其与第一项之后的项合并。

答案 2 :(得分:2)

最佳选择是使用timeout overload为每个项目返回一个超时可观察值,并且还有一个用于订阅(这是您感兴趣的那个)。

observable.timeout(
  () -> Observable.empty().delay(10, TimeUnit.SECONDS),
  o -> Observable.never()
)

我将解释,第一个func0将在subscribe上运行,并将发出一个空的observable(发出完整的)延迟了你想要的时间。 如果在任何物品到达之前经过的时间将会超时,就像您想要的那样。 第二个参数func1将决定项目之间的超时,这是你没有用的,所以我们只是从不通过(没有完成或做任何事情)

另一种选择是 按照Luciano的建议,你可以这样做:

    public static class TimeoutFirst<T> implements Transformer<T,T> {

    private final long timeout;
    private final TimeUnit unit;

    private TimeoutFirst(long timeout, TimeUnit unit) {
        this.timeout = timeout;
        this.unit = unit;
    }

    @Override
    public Observable<T> call(Observable<T> observable) {
        return Observable.amb(observable,
                Observable.timer(timeout, unit).flatMap(aLong -> Observable.error(new TimeoutException("Timeout after " + timeout + " "  + unit.name()))));
    }
}

public static <T> Transformer<T, T> timeoutFirst(long timeout, TimeUnit seconds) {
    return new TimeoutFirst<>(timeout, seconds);
}

使用amb。这是一个非常简洁的解决方案。

答案 3 :(得分:2)

@ndori答案的Kotlin扩展

fun <T> Observable<T>.timeoutFirstMessage(timeout: Long, unit: TimeUnit): Observable<T> {
    return this.timeout<Long, Long>(
        Observable.timer(timeout, unit),
        Function { Observable.never<Long>() }
    )
}

答案 4 :(得分:0)

@ndori答案的RxJava2版本

Observable.timeout(
  Observable.empty().delay(10, TimeUnit.SECONDS),
  o -> Observable.never()
)

Source docs