java - Rxjava - 链 observables
问题描述
请看这段代码:
Disposable disposable = mcityService.authLogin(request,Utils.prepareHeaders())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(resp ->
{
mCompositeDisposable.add(mcityService.getUserDetails(selectedCity.id,Utils.prepareHeaders(resp.tokenType,resp.accessToken))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(userDetails ->
{
/*process resp and user details*/
}));
}, throwable ->
{
process errors
});
mCompositeDisposable.add(disposable);
}
所以基本上我需要调用authLogin
,如果成功,调用(需要调用结果中的getUserDetails
一些字段),如果成功,链完成,我需要两个调用的一些额外处理结果。如果失败或失败,则应该进行错误处理(例如,从 throwable 中获取 http 错误代码或消息)。authLogin
getUserDetails
authLogin
getUserDetails
当我的方法有效时,我知道这不是很好的方法,如何优化它?我可以使用flatMap
运算符而不是嵌套的 observables 吗?
编辑:方法声明:
public static Map<String, String> prepareHeaders(String tokenType, String accessToken);
Observable<UserDetails> getUserDetails(@Path(value = "cityId", encoded = true) String cityId, @HeaderMap Map<String, String> headers);
最后的尝试:
mcityService.authLogin(request, Utils.prepareHeaders())
.concatMap(response ->
{
final Map<String, String> headers = Utils.prepareHeaders(response.tokenType,response.accessToken);
return mcityService.getUserDetails(selectedCity.id, headers)
.map(userDetails -> new Object()
{
public AuthResponse ar = response;
public UserDetails ud = userDetails;
});
})
.doOnNext(responseDetails ->
{
AuthResponse ar = responseDetails.ar;
UserDetails ud = responseDetails.ud;
})
.doOnError(throwable ->
{
final String message = throwable.getMessage();
});
结果:.doOnNext
从未调用,mcityService.getUserDetails
似乎从未调用,.doOnError
也从未调用(因此没有错误)。我真的不需要第一次mcityService.authLogin
通话返回吗?Observable<AuthResponse>
subscribe
解决方案
是的,您可以而且应该使用flatMap
/ concatMap
/ switchMap
。
另外,很抱歉,如果它编码不好,我主要使用 RxJS,它有 pipable 操作符(好多了!)。
mcityService.authLogin(request, Utils.prepareHeaders())
.concatMap(response -> {
final Map<String, String> headers = Utils.prepareHeaders(resp.tokenType,resp.accessToken);
return mcityService.getUserDetails(selectedCity.id, headers)
.map(userDetails -> ResponseUserDetails.of(response, userDetails));
})
.doOnNext(responseDetails -> {
// Hanlde ResponseUserDetails object
})
.doOnError(throwable -> {
// Handle exception
final String message = throwable.getMessage();
...
})
.subscribe(
responseDetails -> { ... },
throwable -> { ... }
);
如果您不想使用其他类,可以Object
即时创建
return mcityService.getUserDetails(selectedCity.id, headers)
.map(userDetails -> new Object() {
public Response r = response;
public UserDetails ud = userDetails;
});
并通过访问其字段
.doOnNext(responseDetails -> {
final Response r = responseDetails.r;
final UserDetails ud = responseDetails.ud;
...
})
static class ResponseUserDetails {
final Response response;
final UserDetails userDetails;
ResponseUserDetails(
final Response response,
final UserDetails userDetails) {
this.response = response;
this.userDetails = userDetails;
}
static ResponseUserDetails of(
final Response response,
final UserDetails userDetails) {
return new ResponseUserDetails(response, userDetails);
}
}
推荐阅读
- reactjs - JSX 属性只能分配一个非空的“表达式”。TS17000
- google-colaboratory - 如何使 TensorFlow SimpleRNN 静态以在 Colab TPU 上进行训练?
- node.js - 如何实现这个异步nodejs网页抓取程序的逻辑?
- jquery - 如何使用 JQuery 为多个 div 的位置设置动画?
- complexity-theory - 两个问题的组合的类别是什么,其中一个是 NP-Complete 问题?
- vim - 如何在 Vim 中使用键绑定运行 pandoc?
- php - PHP中的正则表达式过滤@name或@name.lastname
- c++ - 未定义符号 _stdscr 和 _wgetch
- c# - NET Core 3.1 应用程序设置中的连接字符串与 EntityFramework Core
- c# - 您不应在一个对象上多次调用 Dispose (CA2202)