Kotlin 如何使用retryWhen只有3次就放弃了

Kotlin 如何使用retryWhen只有3次就放弃了,kotlin,rx-java,rx-java2,Kotlin,Rx Java,Rx Java2,我想在执行某些上链函数时过滤特定异常,并尝试只重试整个过程3次,如果仍然失败,则放弃。我得出了这样的结论: val disposable = someFunction(someParameter, delay, subject) .flatMapCompletable { (parameter1, parameter2) -> anotherFunction(parameter1, parameter2, subject) } .retryWhen

我想在执行某些上链函数时过滤特定异常,并尝试只重试整个过程3次,如果仍然失败,则放弃。我得出了这样的结论:

   val disposable = someFunction(someParameter, delay, subject)
    .flatMapCompletable { (parameter1, parameter2) ->
      anotherFunction(parameter1, parameter2, subject)
    }
    .retryWhen { throwable ->
      throwable.filter {
        it.cause?.cause is ExampleException1
            || it.cause?.cause is ExampleException2
            || it.cause is ExampleException3
      }
    }
    .andThen(someStuff())
    .subscribe({
      Timber.d("Finished!")
    }, {
      Timber.d("Failed!")
    })

如何正确操作?

我认为您尝试的操作可以通过
重试来实现

val observable = Observable.defer {
    System.out.println("someMethod called") 
    val result1 = 2 // some value from someMethod()
    Observable.just(result1)
}

observable.flatMap { result ->
    // another method is called here but let's omit it for the sake of simplicity and throw some exception
    System.out.println("someMethod2 called") 
    throw IllegalArgumentException("Exception someMethod2")
    Observable.just("Something that won't be executed anyways")
}.retry { times, throwable ->
            System.out.println("Attempt# " + times)
            // if this condition is true then the retry will occur
            times < 3 && throwable is IllegalArgumentException
        }.subscribe(
                { result -> System.out.println(result) },
                { throwable -> System.out.println(throwable.localizedMessage) })
val observable=observable.defer{
System.out.println(“调用的someMethod”)
val result1=2//someMethod()中的某个值
可观察。仅(结果1)
}
observable.flatMap{result->
//这里调用了另一个方法,但是为了简单起见,让我们省略它,并抛出一些异常
System.out.println(“调用someMethod2”)
抛出IllegalArgumentException(“Exception someMethod2”)
可观察。只是(“无论如何都不会被执行的东西”)
}.重试{次,可丢弃->
System.out.println(“尝试次数”+)
//如果此条件为真,则将进行重试
时间<3&&可丢弃是非法的辩论例外
}.订阅(
{result->System.out.println(result)},
{throwable->System.out.println(throwable.localizedMessage)})
输出:

调用的方法

有人打电话来

尝试#1

调用的方法

有人打电话来

尝试#2

调用的方法

有人打电话来

尝试#3

异常方法2


由于
someMethod2
总是抛出一个
Exception
,在3次尝试后
Exception someMethod2
会打印在观察者的
onError
中。

您可以使用
zipWith
范围来实现这一点

.retryWhen { errors -> errors.zipWith(Observable.range(1, 3), { _, i -> i }) }
retryWhen
操作符提供源发布者的所有错误流。在这里,你可以用数字1,2,3把这些拉链拉上。因此,结果流将发出3个
next
,然后是
complete
。与您可能认为的相反,此重新订阅仅两次,因为在第三次
next
之后立即发出的
complete
会导致整个流完成

您可以进一步扩展此功能,只对某些错误重试,而对其他错误则立即失败。例如,如果只想为
IOException
重试,可以将上述解决方案扩展到:

.retryWhen { errors -> errors
  .zipWith(Observable.range(1, 3), { error, _ -> error })
  .map { error -> when (error) {
    is IOException -> error
    else -> throw error
  }}
}

由于
map
无法在Java中引发选中的异常,Java用户可以出于相同目的使用
flatMap

具有指数延迟的代码:

    YourSingle()
        .retryWhen { errors: Flowable<Throwable> ->
           errors.zipWith(
              Flowable.range(1, retryLimit + 1),
              BiFunction<Throwable, Int, Int> { error: Throwable, retryCount: Int ->
                if (error is RightTypeOfException && retryCount < retryLimit) {
                    retryCount
                } else {
                    throw error
                }
            }
        ).flatMap { retryCount ->
            //exponential 1, 2, 4
            val delay = 2.toDouble().pow(retryCount.toDouble()).toLong() / 2
            Flowable.timer(delay, TimeUnit.SECONDS)
        }
    }
YourSingle()
.retryWhen{错误:可流动->
泽普维思酒店(
流动范围(1,retryLimit+1),
双函数{error:Throwable,retryCount:Int->
if(错误为RightTypeOfException&&retryCount
//指数1,2,4
val delay=2.toDouble().pow(retryCount.toDouble()).toLong()/2
可流动计时器(延迟、时间单位、秒)
}
}

您知道在java中会是怎样的吗代替zipWith,为什么不直接服用(3)?