我想基于Single
中发出的单个值重复onSuccess()
。这是一个有效的例子
import org.reactivestreams.Publisher;
import io.reactivex.Flowable;
import io.reactivex.Single;
import io.reactivex.functions.Function;
public class Temp {
void main() {
Job job = new Job();
Single.just(job)
.map(this::processJob)
.repeatWhen(new Function<Flowable<Object>, Publisher<?>>() {
@Override
public Publisher<?> apply(Flowable<Object> objectFlowable) throws Exception {
// TODO repeat when Single emits false
return null;
}
})
.subscribe();
}
/**
* returns true if process succeeded, false if failed
*/
boolean processJob(Job job) {
return true;
}
class Job {
}
}
我通过依靠“完成”通知来了解repeatWhen
对于Observable的工作方式。但是,由于Single没有收到该通知,所以我不确定Flowable<Object>
到底给了我什么。还有为什么我需要从该函数返回Publisher
?
答案 0 :(得分:1)
代替依赖布尔值,可以使作业失败时引发异常:
class Job {
var isSuccess: Boolean = false
}
fun processJob(job: Job): String {
if (job.isSuccess) {
return "job succeeds"
} else {
throw Exception("job failed")
}
}
val job = Job()
Single.just(job)
.map { processJob(it) }
.retry() // will resubscribe until your job succeeds
.subscribe(
{ value -> print(value) },
{ error -> print(error) }
)
答案 1 :(得分:0)
我在最新的docs和您的代码中发现了一个小差异,所以我做了一些挖掘工作……
(旁注-我认为retryWhen
的语义似乎更适合您的情况,因此我用它代替了repeatWhen
的用法。但是我认为无论哪种情况,您的问题都一样)。
retryWhen
的签名是:
retryWhen(Function<? super Flowable<Throwable>,? extends Publisher<?>> handler)
该参数是工厂函数,其输入是随时onError
发出的源,被称为上游,从而使您能够插入自定义重试逻辑,该逻辑可能会受到基础Throwable
的询问而影响。这开始回答您的第一个问题:“我不确定Flowable<Object>
到底给了我什么”-开头不应该是Flowable<Object>
,应该是Flowable<Throwable>
(由于我刚才描述的原因)。
那么Flowable<Object>
是哪里来的?我通过使用RxJava版本2.1.17
的自动完成功能设法重现了IntelliJ的代码生成。但是,升级到2.2.0
会产生Flowable<Throwable>
的正确结果。因此,请查看是否升级到最新版本也会为您生成正确的结果。
关于您的第二个问题:“为什么还要从此函数返回Publisher
?” -这用于确定是否应该进行重新订阅。如果工厂函数返回一个发出终端状态的Publisher
(即调用onError()
或onComplete()
),则不会进行重新订阅。但是,如果调用onNext()
,它将调用。 (这也解释了为什么不键入Publisher
-类型无关紧要。唯一重要的是它发布的是哪种通知)。
结合上述内容的另一种重写方法可能如下:
// just some type to use as a signal to retry
private class SpecialException extends RuntimeException {}
// job processing results in a Completable that either completes or
// doesn't (by way of an exception)
private Completable rxProcessJob(Job job) {
return Completable.complete();
// return Completable.error(new SpecialException());
}
...
rxProcessJob(new Job())
.retryWhen(errors -> {
return errors.flatMap(throwable -> {
if(throwable instanceof SpecialException) {
return PublishProcessor.just(1);
}
return PublishProcessor.error(throwable);
});
})
.subscribe(
() -> {
System.out.println("## onComplete()");
},
error -> {
System.out.println("## onError(" + error.getMessage() + ")");
}
);
我希望有帮助!
答案 2 :(得分:0)
被接受的答案会起作用,但是有点黑。您无需抛出错误;只需过滤processJob
的输出即可将Single
转换为Maybe
,然后使用repeatWhen
处理程序来决定您想要多少次或延迟多少时间重新订阅。请从下面的示例中查看Kotlin代码,您应该可以轻松地将其转换为Java。
filter { it }
.repeatWhen { handler ->
handler.zipWith(1..3) { _, i -> i }
.flatMap { retryCount -> Flowable.timer(retryDelay.toDouble().pow(retryCount).toLong(), TimeUnit.SECONDS) }
.doOnNext { log.warn("Retrying...") }
}