如何在 RxJava 出错后更改重试请求中的参数
How to change parameters in retry request after error in RxJava
我向带有改造 2.0 的服务器发送登录请求,并向客户端会话令牌发送服务器 return,我必须在其他请求中使用它,但此令牌的生命周期有限,并且何时可用过期服务器 returns HTTP 错误 401。
我尝试重新登录,在收到此错误后,在下一个代码的帮助下:
holder.getApi(GuideProfileApi.class)
.getProfile(String.valueOf(holder.getServerId()), holder.getServerToken())
.subscribeOn(Schedulers.io())
.retryWhen(new Function<Observable<Throwable>, ObservableSource<?>>() {
@Override
public ObservableSource<?> apply(Observable<Throwable> throwableObservable) throws Exception {
return throwableObservable.flatMap(new Function<Throwable, ObservableSource<?>>() {
@Override
public ObservableSource<?> apply(Throwable throwable) throws Exception {
if (throwable instanceof HttpException && ((HttpException)throwable).code() == 401) {
RegistryLoginResult loginResult = holder.login().blockingSingle();
return holder.getApi(GuideProfileApi.class)
.getProfile(String.valueOf(loginResult.getUserId()), loginResult.getSessionToken());
}
return Observable.error(throwable);
}
});
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<ProfileResult>() {
@Override
public void accept(ProfileResult profileResult) throws Exception {
Log.d("Result", profileResult.toString());
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
Log.e("Result", throwable.getLocalizedMessage());
}
});
并发送重试请求,但请求参数与错误请求(重新登录前)相同。如何在再次发送之前更改请求的参数?
您用错了运算符。如果遇到错误,retryWhen
将重试您的 原始可观察对象 。你需要的是onErrorResumeNext
。像
holder.getApi(GuideProfileApi.class)
.getProfile(String.valueOf(holder.getServerId()), holder.getServerToken())
.subscribeOn(Schedulers.io())
.onErrorResumeNext(new Function<Throwable, ObservableSource<?>>() {
@Override
public ObservableSource<?> apply(Throwable throwable) {
if (throwable instanceof HttpException && ((HttpException)throwable).code() == 401) {
RegistryLoginResult loginResult = holder.login().blockingSingle();
return holder.getApi(GuideProfileApi.class)
.getProfile(String.valueOf(loginResult.getUserId()), loginResult.getSessionToken());
}
return Observable.error(throwable);
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<ProfileResult>() {
@Override
public void accept(ProfileResult profileResult) throws Exception {
Log.d("Result", profileResult.toString());
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
Log.e("Result", throwable.getLocalizedMessage());
}
});
您可以使用retryWhen
,但问题是您的retryWhen 会重试您在惰性时刻创建的同一个可观察对象。
您在这里的解决方案是使用运算符 defer
来获取 host(),因为 defer 它不是在您定义它时创建可观察对象,而是在它被订阅者使用时创建。
Observable.defer(()-> holder.getApi(GuideProfileApi.class)
.getProfile(String.valueOf(holder.getServerId()),holder.getServerToken()))
.subscribeOn(Schedulers.io())
.retryWhen(new Function<Observable<Throwable>, ObservableSource<?>>() {
@Override
public ObservableSource<?> apply(Observable<Throwable> throwableObservable) throws Exception {
return throwableObservable.flatMap(new Function<Throwable, ObservableSource<?>>() {
@Override
public ObservableSource<?> apply(Throwable throwable) throws Exception {
if (throwable instanceof HttpException && ((HttpException)throwable).code() == 401) {
RegistryLoginResult loginResult = holder.login().blockingSingle();
return holder.getApi(GuideProfileApi.class)
.getProfile(String.valueOf(loginResult.getUserId()), loginResult.getSessionToken());
}
return Observable.error(throwable);
}
});
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<ProfileResult>() {
@Override
public void accept(ProfileResult profileResult) throws Exception {
Log.d("Result", profileResult.toString());
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
Log.e("Result", throwable.getLocalizedMessage());
}
});
你可以在这里看到一些重试的例子https://github.com/politrons/reactive/blob/master/src/test/java/rx/observables/errors/ObservableExceptions.java
我向带有改造 2.0 的服务器发送登录请求,并向客户端会话令牌发送服务器 return,我必须在其他请求中使用它,但此令牌的生命周期有限,并且何时可用过期服务器 returns HTTP 错误 401。
我尝试重新登录,在收到此错误后,在下一个代码的帮助下:
holder.getApi(GuideProfileApi.class)
.getProfile(String.valueOf(holder.getServerId()), holder.getServerToken())
.subscribeOn(Schedulers.io())
.retryWhen(new Function<Observable<Throwable>, ObservableSource<?>>() {
@Override
public ObservableSource<?> apply(Observable<Throwable> throwableObservable) throws Exception {
return throwableObservable.flatMap(new Function<Throwable, ObservableSource<?>>() {
@Override
public ObservableSource<?> apply(Throwable throwable) throws Exception {
if (throwable instanceof HttpException && ((HttpException)throwable).code() == 401) {
RegistryLoginResult loginResult = holder.login().blockingSingle();
return holder.getApi(GuideProfileApi.class)
.getProfile(String.valueOf(loginResult.getUserId()), loginResult.getSessionToken());
}
return Observable.error(throwable);
}
});
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<ProfileResult>() {
@Override
public void accept(ProfileResult profileResult) throws Exception {
Log.d("Result", profileResult.toString());
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
Log.e("Result", throwable.getLocalizedMessage());
}
});
并发送重试请求,但请求参数与错误请求(重新登录前)相同。如何在再次发送之前更改请求的参数?
您用错了运算符。如果遇到错误,retryWhen
将重试您的 原始可观察对象 。你需要的是onErrorResumeNext
。像
holder.getApi(GuideProfileApi.class)
.getProfile(String.valueOf(holder.getServerId()), holder.getServerToken())
.subscribeOn(Schedulers.io())
.onErrorResumeNext(new Function<Throwable, ObservableSource<?>>() {
@Override
public ObservableSource<?> apply(Throwable throwable) {
if (throwable instanceof HttpException && ((HttpException)throwable).code() == 401) {
RegistryLoginResult loginResult = holder.login().blockingSingle();
return holder.getApi(GuideProfileApi.class)
.getProfile(String.valueOf(loginResult.getUserId()), loginResult.getSessionToken());
}
return Observable.error(throwable);
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<ProfileResult>() {
@Override
public void accept(ProfileResult profileResult) throws Exception {
Log.d("Result", profileResult.toString());
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
Log.e("Result", throwable.getLocalizedMessage());
}
});
您可以使用retryWhen
,但问题是您的retryWhen 会重试您在惰性时刻创建的同一个可观察对象。
您在这里的解决方案是使用运算符 defer
来获取 host(),因为 defer 它不是在您定义它时创建可观察对象,而是在它被订阅者使用时创建。
Observable.defer(()-> holder.getApi(GuideProfileApi.class)
.getProfile(String.valueOf(holder.getServerId()),holder.getServerToken()))
.subscribeOn(Schedulers.io())
.retryWhen(new Function<Observable<Throwable>, ObservableSource<?>>() {
@Override
public ObservableSource<?> apply(Observable<Throwable> throwableObservable) throws Exception {
return throwableObservable.flatMap(new Function<Throwable, ObservableSource<?>>() {
@Override
public ObservableSource<?> apply(Throwable throwable) throws Exception {
if (throwable instanceof HttpException && ((HttpException)throwable).code() == 401) {
RegistryLoginResult loginResult = holder.login().blockingSingle();
return holder.getApi(GuideProfileApi.class)
.getProfile(String.valueOf(loginResult.getUserId()), loginResult.getSessionToken());
}
return Observable.error(throwable);
}
});
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<ProfileResult>() {
@Override
public void accept(ProfileResult profileResult) throws Exception {
Log.d("Result", profileResult.toString());
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
Log.e("Result", throwable.getLocalizedMessage());
}
});
你可以在这里看到一些重试的例子https://github.com/politrons/reactive/blob/master/src/test/java/rx/observables/errors/ObservableExceptions.java