如何捕获失败的呼叫并继续其余的网络呼叫?
我正在进行5个并行网络调用,模拟其中4个成功,1个失败。
失败的调用会导致整个Single.zip()
失败,并且我无法获取其他4个网络调用的结果,即使它们已经成功。
如何处理Single.zip()
中单个网络调用失败的错误,并获取成功的网络调用的结果?
private Single<BigInteger> createNetworkCall(){
return Single.fromCallable(() -> {
return service.getBalance("validaddress").execute();
}).subscribeOn(Schedulers.io());
}
private Single<BigInteger> createFailedNetworkCall(){
return Single.fromCallable(() -> {
return service.getBalance("invalidaddress").execute();
}).subscribeOn(Schedulers.io());
}
private void makeParallelCalls(){
List<Single<BigInteger>> iterable = new ArrayList<>();
iterable.add(createNetworkCall());
iterable.add(createNetworkCall());
iterable.add(createNetworkCall());
iterable.add(createNetworkCall());
iterable.add(createFailedNetworkCall());
Single.zip(iterable, (results) -> {
Log.d(TAG, "makeParallelCalls: " + Arrays.toString(results));
return results;
}).observeOn(AndroidSchedulers.mainThread())
.subscribe(results-> {
Log.d(TAG, "onSuccess: makeParallelCalls: " + results);
}, (exception) -> {
Log.e(TAG, "onError: makeParallelCalls", exception);
});
}
解决方案
捕获异常,不允许该错误中断Single.Zip。
例如,在您的请求工厂中,返回可选而不是响应。
private Single<Optional<Long>> performNetworkCall(int n){
return Single.fromCallable(() -> {
if (n % 2 == 0) {
throw new Exception("failed call");
}
return 0L;
}).subscribeOn(Schedulers.io())
.map(Optional::of)
.onErrorReturnItem(Optional.empty());
// or .onErrorReturn(exception -> Optional.empty());
}
private void makeParallelCalls(){
List<Single<BigInteger>> iterable = new ArrayList<>();
iterable.add(performNetworkCall(1));
iterable.add(performNetworkCall(2));
iterable.add(performNetworkCall(3));
iterable.add(performNetworkCall(4));
iterable.add(performNetworkCall(5));
Single.zip(iterable, (results) -> {
for (Object result : results) {
var optional = (Optional<Integer>)result;
if (optional.isEmpty()) {
// this one failed, no data
} else {
var response = optional.get();
}
}
return results;
});
}
您可以将可选替换为包含附加信息的自定义类,例如导致失败的异常或错误信息。
如果您有恢复选项,则可以改用.onErrorResumeNext
。
相关文章