我正在实现一个可观察的对象,它在延迟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上的博客文章。
答案 0 :(得分:5)
请再次浏览Dan Lew的博客文章,其中他在 Uses 标题下实际描述了您的用例的解决方案。
source.retryWhen(errors -> errors.flatMap(error -> Observable.timer(5, TimeUnit.SECONDS)))
说明:
请注意Observable.delay
和Observable.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({}, {})