Rxjava重试立即调用

时间:2017-10-25 07:15:19

标签: java rx-java

我对rxjava有一个非常具体的问题或误解,有人希望可以提供帮助。

我正在运行rxjava 2.1.5并拥有以下代码片段:

public static void main(String[] args) {

    final Observable<Object> observable = Observable.create(emitter -> {
        // Code ... 
    });

    observable.subscribeOn(Schedulers.io())
            .retryWhen(error -> {
                System.out.println("retryWhen");
                return error.retry();
            }).subscribe(next -> System.out.println("subscribeNext"),
                         error -> System.out.println("subscribeError"));

}

执行此操作后,程序将打印:

retryWhen

Process finished with exit code 0

我的问题,我不明白的是:为什么重试在订阅Observable时立即调用?观察者什么都不做。

我想要的是重试当在发射器上调用onError时被调用。我误解了rx是如何工作的吗?

谢谢!

添加新代码段:

public static void main(String[] args) throws InterruptedException {

    final Observable<Object> observable = Observable.create(emitter -> {
        emitter.onNext("next");
        emitter.onComplete();
    });

    final CountDownLatch latch = new CountDownLatch(1);
    observable.subscribeOn(Schedulers.io())
            .doOnError(error -> System.out.println("doOnError: " + error.getMessage()))
            .retryWhen(error -> {
                System.out.println("retryWhen: " + error.toString());
                return error.retry();
            }).subscribe(next -> System.out.println("subscribeNext"),
                         error -> System.out.println("subscribeError"),
                         () -> latch.countDown());

    latch.await();
}

调用发射器onNext和complete。永远不会调用DoOnError。输出是:

retryWhen:io.reactivex.subjects.SerializedSubject@35fb3008 subscribeNext

处理完成,退出代码为0

2 个答案:

答案 0 :(得分:1)

retryWhen订阅它时,

Observer会调用提供的函数,因此您的主序列会附带一个序列,该序列会发出主序列失败的Throwable。你应该在Observable Function中构建一个逻辑,所以最后,一个Throwable会在另一端产生一个值。

Observable.error(new IOException())
    .retryWhen(e -> {
         System.out.println("Setting up retryWhen");
         int[] count = { 0 };
         return e
            .takeWhile(v -> ++count[0] < 3)
            .doOnNext(v -> { System.out.println("Retrying"); });
    })
    .subscribe(System.out::println, Throwable::printStackTrace);

由于为每个订阅者执行了e -> { }函数体,因此您可以安全地使用每个订阅者状态,例如重试计数器。

使用e -> e.retry()无效,因为输入错误流永远不会被onError调用。

答案 1 :(得分:0)

一个问题是,您没有收到任何结果,因为您使用retryWhen()创建了一个Thread,但您的应用程序似乎已完成。要查看该行为,您可能需要使用while循环来保持应用运行。

这实际上意味着您需要在代码末尾添加类似内容:

onNext()

另一个问题是您不会在样本中发出任何错误。您需要发出至少一个值来调用.retryWhen(errors -> errors) ,否则它不会重复,因为它正在等待它。

这是一个值的工作示例,然后它发出错误并重复。你可以用

.retryWhen(errors -> errors.retry())

相同
 public static void main(String[] args) {
        Observable
                .create(e -> {
                    e.onNext("test");
                    e.onError(new Throwable("test"));
                })
                .retryWhen(errors -> errors.retry())
                .subscribeOn(Schedulers.io())
                .subscribe(
                        next -> System.out.println("subscribeNext"),
                        error -> System.out.println("subscribeError"),
                        () -> System.out.println("onCompleted")
                );

        while (true) {

        }
    }

工作样本:

Observable
            .create(e -> e.onError(new Exception("empty")))
            .doOnError(e -> System.out.println("error received " + e))
            .retryWhen(errors -> errors.retry())
            .subscribeOn(Schedulers.io())
            .subscribe(
                    nextOrSuccess -> System.out.println("nextOrSuccess " + nextOrSuccess),
                    error -> System.out.println("subscribeError")
            );

你需要发出结果的原因是,Observable需要发出一个值,否则它会等到它收到一个新值。

这是因为onError只能被称为onec(在订阅中),但是onNext会发出1 .. *值。

您可以使用doOnError()检查此行为,每次重试Observable时都会向您提供错误。

{{1}}