我有两个异步方法,必须在一次操作中调用它。每种方法都可以成功完成,或者会出错。如果出现错误,我必须重试2秒以再次尝试调用每个方法。意思是,尽管其中一个方法有结果,但我应该同时调用这两个方法。在错误回调中,我想知道发生在哪种方法中的错误,或两种方法中都发生了错误。
似乎我应该为此使用Completable
,但在Rx中我绝对是新手。
private void method1(final CompletableEmitter e, String path){
Database.getInstance().getReference(path).addListener(new Listener() {
@Override
public void onDataChange(Data data) {
//todo something
e.onComplete();
}
@Override
public void onCancelled(DatabaseError databaseError) {
e.onError(new Throwable(databaseError.getMessage()));
}
});
}
方法2相同。 以下代码无法正常工作。
Completable completable1 = Completable.create(method1(e););
Completable completable2 = Completable.create(method2(e););
completable1
.doOnError(…)
.retry(1)
.andThen(completable2 //never called if completable1 gets onError each time
.retry(1)
.doOnError(…))
.subscribe(…).dispose();
答案 0 :(得分:1)
您有很多方法可以做到这一点。我仅是为了解释一下如何使用两个Completable
假设您有两个完成项:
Completable doSomething = ...
Completable doSomethingElse = ...
要顺序执行这些命令,
您可以使用andThen
运算符来连接它们。然后,要在发生错误时延迟重试,可以使用retryWhen
:
doSomething.andThen(doSomethingElse)
.retryWhen { Flowable.timer(2, TimeUnit.SECONDS) }
.subscribe()
如果永久性发生错误,则以上代码段将无限重试。要超越此限制,您可以使用以下方法限制尝试次数:
.retryWhen { errors ->
val retryCounter = AtomicInteger()
errors.flatMap {
if (retryCounter.getAndIncrement() <= 3)
Flowable.timer(2, TimeUnit.SECONDS)
else Flowable.error(it)
}
}
如果仅在发生给定类型的错误时才想重试,则可以使用:
.retryWhen { errors ->
val retryCounter = AtomicInteger()
errors.flatMap {
if (it is YourSpecficError && retryCounter.getAndIncrement() <= 3)
Flowable.timer(2, TimeUnit.SECONDS)
else Flowable.error(it)
}
}
如果要独立重试每个,则可以使用:
doSomething.retryWhen { ... }
.andThen(doSomethingElse.retryWhen { ... })
.subscribe()
此外,为了避免重试逻辑重复,您可以将其封装在扩展函数中:
fun Completable.retryDelayed(): Completable {
return this.retryWhen { errors ->
val retryCounter = AtomicInteger()
errors.flatMap {
if (it is YourSpecficError && retryCounter.getAndIncrement() <= 3)
Flowable.timer(2, TimeUnit.SECONDS)
else Flowable.error(it)
}
}
}
如果要并行运行互补项,则可以使用merge
运算符:
Completable doAll = Completable.merge(listOf(doSomething, doSomething))