RxJava 线性退避,在重试时传递较早的日期参数
RxJava linear backoff, passing in earlier date parameters on retry
我正在重构一些代码,这些代码会调用带有格式化日期参数(例如“2016-3-10”)的 Web 服务,如果返回 null,有一天会触发另一个带有日期的方法更早(如“2016-3-9”)。这将至少重试 3 次。
我正在将其重构到 RxJava 中,但不确定如何实施退避策略或在这种情况下使用哪个 .retry()
或 .retryWhen()
运算符。
我使用 Retrofit 让 Web 服务返回通常的 Observable
。
这是我目前拥有的:
PictureService pictureService = retrofit.create(PictureService.class);
pictureService.getPhotos(date)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.retry() //Some retry
...
.subscribe()
那么这里最好使用哪个运算符来重试请求,当当前日期 returns 为空时,我应该如何将新日期传递给 getPhotos()
请求?
为了完成这里是上面提到的 Retrofit 服务:
@GET("/someurl/photos?api_key=xxxxxxx")
Observable<PictureAPI> getPhotos(@Query("earth_date") String earthDate);
好的,现在我可以再次回答这个问题了,我们开始吧:
Observable.just("2016-3-10", "2016-3-9", "2016-3-8")
.concatMap(date -> pictureService.getPhotos(date))
.filter(response -> response != null)
.take(1)...
有关详细说明,请查看 Dan Lew 的博客 post:http://blog.danlew.net/2015/06/22/loading-data-from-multiple-sources-with-rxjava/
简而言之:concat
(和 concatMap
)将订阅每个新的 Observable
只有在前一个发出 onCompleted
并且仅当需要更多项目时下游。 take(1)
将在第一个非 null
响应后取消订阅,因此 concatMap
将不会订阅下一个 Observable
.
编辑: 要检查是否真的只发送了一个请求,您可以
1.) 在 Retrofit 中启用日志记录(如果您是最新版本,请在 OkHttpClient
中添加 Interceptor
)。这使您可以直接观察正在发送的请求。
2.) 添加一个 doOnSubscribe()
像这样:
.concatMap(date -> pictureService.getPhotos(date)
.doOnSubscribe(new Action0() {
@Override
public void call() {
Log.d(TAG, "sending request for " + date);
}
});
)
由于 Retrofit 请求仅在订阅时发送,当且仅当随后发送请求时,日志消息才会出现。
我正在重构一些代码,这些代码会调用带有格式化日期参数(例如“2016-3-10”)的 Web 服务,如果返回 null,有一天会触发另一个带有日期的方法更早(如“2016-3-9”)。这将至少重试 3 次。
我正在将其重构到 RxJava 中,但不确定如何实施退避策略或在这种情况下使用哪个 .retry()
或 .retryWhen()
运算符。
我使用 Retrofit 让 Web 服务返回通常的 Observable
。
这是我目前拥有的:
PictureService pictureService = retrofit.create(PictureService.class);
pictureService.getPhotos(date)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.retry() //Some retry
...
.subscribe()
那么这里最好使用哪个运算符来重试请求,当当前日期 returns 为空时,我应该如何将新日期传递给 getPhotos()
请求?
为了完成这里是上面提到的 Retrofit 服务:
@GET("/someurl/photos?api_key=xxxxxxx")
Observable<PictureAPI> getPhotos(@Query("earth_date") String earthDate);
好的,现在我可以再次回答这个问题了,我们开始吧:
Observable.just("2016-3-10", "2016-3-9", "2016-3-8")
.concatMap(date -> pictureService.getPhotos(date))
.filter(response -> response != null)
.take(1)...
有关详细说明,请查看 Dan Lew 的博客 post:http://blog.danlew.net/2015/06/22/loading-data-from-multiple-sources-with-rxjava/
简而言之:concat
(和 concatMap
)将订阅每个新的 Observable
只有在前一个发出 onCompleted
并且仅当需要更多项目时下游。 take(1)
将在第一个非 null
响应后取消订阅,因此 concatMap
将不会订阅下一个 Observable
.
编辑: 要检查是否真的只发送了一个请求,您可以
1.) 在 Retrofit 中启用日志记录(如果您是最新版本,请在 OkHttpClient
中添加 Interceptor
)。这使您可以直接观察正在发送的请求。
2.) 添加一个 doOnSubscribe()
像这样:
.concatMap(date -> pictureService.getPhotos(date)
.doOnSubscribe(new Action0() {
@Override
public void call() {
Log.d(TAG, "sending request for " + date);
}
});
)
由于 Retrofit 请求仅在订阅时发送,当且仅当随后发送请求时,日志消息才会出现。