使用retryWhen()重试可观察对象

时间:2018-08-13 12:41:26

标签: java android rx-java observable rx-java2

我正在实现一个可观察的对象,它在延迟5秒后会重试错误。我正在对网络进行改造。我面临的问题是,当API返回错误时,会有很多重试。我只想在5秒后重试,但是重试发生的速度非常疯狂(每秒几乎3次)。知道为什么吗?

userAPI.getUsers()
       .filter { it.users.isNotEmpty() }
       .subscribeOn(Schedulers.io())
       .retryWhen { errors -> errors.flatMap { errors.delay(5, TimeUnit.SECONDS) } }
       .observeOn(AndroidSchedulers.mainThread())
       .subscribe({}, {})

其中userAPI.getUsers()返回一个可观察值。

疯狂的API请求数:

08-13 12:31:31.308 26277-26453/com.app.user.dummy D/OkHttp: --> GET https://userapi.com/foo
08-13 12:31:31.825 26277-26453/com.app.user.dummy D/OkHttp: --> GET https://userapi.com/foo
08-13 12:31:32.370 26277-26453/com.app.user.dummy D/OkHttp: --> GET https://userapi.com/foo
08-13 12:31:32.897 26277-26453/com.app.user.dummy D/OkHttp: --> GET https://userapi.com/foo
08-13 12:31:33.436 26277-26453/com.app.user.dummy D/OkHttp: --> GET https://userapi.com/foo
08-13 12:31:33.952 26277-26453/com.app.user.dummy D/OkHttp: --> GET https://userapi.com/foo
08-13 12:31:34.477 26277-26453/com.app.user.dummy D/OkHttp: --> GET https://userapi.com/foo
08-13 12:31:35.020 26277-26453/com.app.user.dummy D/OkHttp: --> GET https://userapi.com/foo
08-13 12:31:35.609 26277-26453/com.app.user.dummy D/OkHttp: --> GET https://userapi.com/foo
08-13 12:31:36.205 26277-26453/com.app.user.dummy D/OkHttp: --> GET https://userapi.com/foo

P.S:我已经看过Dan Lew在retryWhen和repeatWhen上的博客文章。

2 个答案:

答案 0 :(得分:5)

请再次浏览Dan Lew的博客文章,其中他在 Uses 标题下实际描述了您的用例的解决方案。

source.retryWhen(errors -> errors.flatMap(error -> Observable.timer(5, TimeUnit.SECONDS)))

说明:

请注意Observable.delayObservable.timer之间的区别,因为Observable.delay的文档指出

  

来自Observable源的错误通知不会延迟。

在重试中立即订阅您的errors可观察对象(因为Observable.delay仅延迟onNext),然后源错误再次发出并立即发出错误,这将触发retryWhen并进入递归循环。

答案 1 :(得分:0)

问题似乎出在您的flatmap函数lambda中,即

.retryWhen({ errors -> errors.flatMap { errors.delay(5, TimeUnit.SECONDS) } })

(我假设缺少方括号是一个错字)。结果是传递给retryWhen的Observable立即终止,从而在您收到错误时导致“疯狂”的重试率。

尝试

userAPI.getUsers()
   .filter { it.users.isNotEmpty() }
   .subscribeOn(Schedulers.io())
   .retryWhen({ errors -> errors.flatMap { error -> Observable.just(1).delay(5, TimeUnit.SECONDS) } })
   .observeOn(AndroidSchedulers.mainThread())
   .subscribe({}, {})