我是 RxJava 的新手,但我正在将它集成到我正在从事的项目中以帮助我学习它。我遇到了一个关于最佳实践的问题。
我有一个关于如何处理onError
以防止停止Observable
处理的问题。
这是设置:
对于每个我想做 2 个或更多网络请求的用户 ID,我都有一个用户 ID 列表。如果用户 ID 的任何网络请求失败,则该用户 ID 将不会更新并且可以跳过。这不应阻止处理其他用户标识。我确实有一个解决方案,但它涉及嵌套订阅(参见第二个代码块)。我确实看到的一个问题是,如果每个呼叫失败,即使在检测到某个阈值数量失败后,也无法短路并阻止其余呼叫访问网络资源。
有一个更好的方法吗?
在传统代码中:
List<String> results = new ArrayList<String>();
for (String userId : userIds) {
try {
String info = getInfo(userId); // can throw an GetInfoException
String otherInfo = getOtherInfo(userId); // can throw an GetOtherInfoException
results.add(info + ", " + otherInfo);
} catch (GetInfoException e) {
log.error(e);
} catch (GetOtherInfoException e) {
log.error(e);
}
}
问题:
伪代码:
userid -> network requests -> result
1 -> a, b -> onNext(1[a ,b])
2 -> a, onError -> onError
3 -> a, b -> onNext(3[a, b])
4 -> a, b -> onNext(4[a, b])
以下是 userIds 列表和每 2 个信息请求的工作示例。如果你运行它,你会看到它会失败(见下面的源代码)
import rx.Observable;
import rx.Observable.OnSubscribeFunc;
import rx.Observer;
import rx.Subscription;
import rx.subscriptions.Subscriptions;
import rx.util.functions.Action0;
import rx.util.functions.Action1;
import rx.util.functions.Func1;
public class TestMergeDelayError {
public static Observable<String> getUserIds() {
return Observable.from(new String[]{"1", "2", "3", "4", "5", "6"});
}
public static Observable<String> getInfo(final String prefix, final String integer, final String errorNumber) {
Observable<String> observable = Observable.create(new OnSubscribeFunc<String>() {
public Subscription onSubscribe(Observer<? super String> t1) {
if (integer.contains(errorNumber)) {
t1.onError(new Exception());
} else {
t1.onNext(prefix + integer);
t1.onCompleted();
}
return Subscriptions.empty();
}
});
return observable;
}
public static void main(String[] args) {
Observable<String> userIdObservable = getUserIds();
Observable<String> t = userIdObservable.flatMap(new Func1<String, Observable<String>>() {
public Observable<String> call(final String t1) {
Observable<String> info1 = getInfo("1::: ", t1, "2");
Observable<String> info2 = getInfo("2::: ",t1, "3");
return Observable.mergeDelayError(info1, info2);
}
});
t.subscribe(new Action1<String>() {
public void call(String t1) {
System.out.println(t1);
}
}, new Action1<Throwable>() {
public void call(Throwable t1) {
t1.printStackTrace();
}
},
new Action0(){
public void call() {
System.out.println("onComplete");
}
});
}
}
输出:
1::: 1
2::: 1
2::: 2
java.lang.Exception
at TestMergeDelayError$1.onSubscribe(TestMergeDelayError.java:32)
at rx.Observable.subscribe(Observable.java:241)
at rx.operators.OperationMergeDelayError$MergeDelayErrorObservable$ParentObserver.onNext(OperationMergeDelayError.java:266)
at rx.operators.OperationMergeDelayError$MergeDelayErrorObservable$ParentObserver.onNext(OperationMergeDelayError.java:210)
at rx.operators.OperationMergeDelayError$2.onSubscribe(OperationMergeDelayError.java:77)
at rx.Observable.subscribe(Observable.java:241)
at rx.operators.OperationMergeDelayError$MergeDelayErrorObservable.onSubscribe(OperationMergeDelayError.java:171)
at rx.operators.OperationMergeDelayError$1.onSubscribe(OperationMergeDelayError.java:64)
at rx.Observable.subscribe(Observable.java:241)
at rx.operators.OperationMerge$MergeObservable$ParentObserver.onNext(OperationMerge.java:164)
at rx.operators.OperationMerge$MergeObservable$ParentObserver.onNext(OperationMerge.java:116)
at rx.operators.OperationMap$MapObservable$1.onNext(OperationMap.java:105)
at rx.operators.SafeObserver.onNext(SafeObserver.java:102)
at rx.operators.OperationToObservableIterable$ToObservableIterable.onSubscribe(OperationToObservableIterable.java:94)
at rx.Observable.subscribe(Observable.java:241)
at rx.operators.OperationMap$MapObservable.onSubscribe(OperationMap.java:102)
at rx.operators.OperationMap$2.onSubscribe(OperationMap.java:76)
at rx.Observable.subscribe(Observable.java:241)
at rx.operators.OperationMerge$MergeObservable.onSubscribe(OperationMerge.java:106)
at rx.operators.OperationMerge$1.onSubscribe(OperationMerge.java:56)
at rx.Observable.subscribe(Observable.java:241)
at rx.Observable.protectivelyWrapAndSubscribe(Observable.java:320)
at rx.Observable.subscribe(Observable.java:483)
嵌套订阅解决方案:
import rx.Observable;
import rx.Observable.OnSubscribeFunc;
import rx.Observer;
import rx.Subscription;
import rx.subscriptions.Subscriptions;
import rx.util.functions.Action0;
import rx.util.functions.Action1;
import rx.util.functions.Func1;
public class TestMergeDelayError {
public static Observable<String> getUserIds() {
return Observable.from(new String[]{"1", "2", "3", "4", "5", "6"});
}
public static Observable<String> getInfo(final String prefix, final String integer, final String errorNumber) {
Observable<String> observable = Observable.create(new OnSubscribeFunc<String>() {
public Subscription onSubscribe(Observer<? super String> t1) {
if (integer.contains(errorNumber)) {
t1.onError(new Exception());
} else {
t1.onNext(prefix + integer);
t1.onCompleted();
}
return Subscriptions.empty();
}
});
return observable;
}
public static void main(String[] args) {
Observable<String> userIdObservable = getUserIds();
userIdObservable.subscribe(new Action1<String>() {
public void call(String t1) {
Observable<String> info1 = getInfo("1::: ", t1, "2");
Observable<String> info2 = getInfo("2::: ", t1, "3");
Observable.merge(info1, info2).subscribe(new Action1<String>() {
public void call(String t1) {
System.out.println(t1);
}
}, new Action1<Throwable>() {
public void call(Throwable t1) {
t1.printStackTrace();
}
},
new Action0() {
public void call() {
System.out.println("onComplete");
}
});
}
});
}
}
输出:
1::: 1
2::: 1
onComplete
java.lang.Exception
at TestMergeDelayError$1.onSubscribe(TestMergeDelayError.java:28)
at rx.Observable.subscribe(Observable.java:241)
at rx.operators.OperationMerge$MergeObservable$ParentObserver.onNext(OperationMerge.java:164)
at rx.operators.OperationMerge$MergeObservable$ParentObserver.onNext(OperationMerge.java:116)
at rx.operators.OperationToObservableIterable$ToObservableIterable.onSubscribe(OperationToObservableIterable.java:94)
at rx.Observable.subscribe(Observable.java:241)
at rx.operators.OperationMerge$MergeObservable.onSubscribe(OperationMerge.java:106)
at rx.operators.OperationMerge$1.onSubscribe(OperationMerge.java:56)
at rx.Observable.subscribe(Observable.java:241)
at rx.Observable.protectivelyWrapAndSubscribe(Observable.java:320)
at rx.Observable.subscribe(Observable.java:483)
at TestMergeDelayError$2.call(TestMergeDelayError.java:47)
at TestMergeDelayError$2.call(TestMergeDelayError.java:42)
at rx.Observable$2.onNext(Observable.java:381)
at rx.operators.SafeObserver.onNext(SafeObserver.java:102)
at rx.operators.OperationToObservableIterable$ToObservableIterable.onSubscribe(OperationToObservableIterable.java:94)
at rx.Observable.subscribe(Observable.java:241)
at rx.Observable.protectivelyWrapAndSubscribe(Observable.java:320)
at rx.Observable.subscribe(Observable.java:367)
at TestMergeDelayError.main(TestMergeDelayError.java:42)
1::: 3
java.lang.Exception
at TestMergeDelayError$1.onSubscribe(TestMergeDelayError.java:28)
at rx.Observable.subscribe(Observable.java:241)
at rx.operators.OperationMerge$MergeObservable$ParentObserver.onNext(OperationMerge.java:164)
at rx.operators.OperationMerge$MergeObservable$ParentObserver.onNext(OperationMerge.java:116)
at rx.operators.OperationToObservableIterable$ToObservableIterable.onSubscribe(OperationToObservableIterable.java:94)
at rx.Observable.subscribe(Observable.java:241)
at rx.operators.OperationMerge$MergeObservable.onSubscribe(OperationMerge.java:106)
at rx.operators.OperationMerge$1.onSubscribe(OperationMerge.java:56)
at rx.Observable.subscribe(Observable.java:241)
at rx.Observable.protectivelyWrapAndSubscribe(Observable.java:320)
at rx.Observable.subscribe(Observable.java:483)
at TestMergeDelayError$2.call(TestMergeDelayError.java:47)
at TestMergeDelayError$2.call(TestMergeDelayError.java:42)
at rx.Observable$2.onNext(Observable.java:381)
at rx.operators.SafeObserver.onNext(SafeObserver.java:102)
at rx.operators.OperationToObservableIterable$ToObservableIterable.onSubscribe(OperationToObservableIterable.java:94)
at rx.Observable.subscribe(Observable.java:241)
at rx.Observable.protectivelyWrapAndSubscribe(Observable.java:320)
at rx.Observable.subscribe(Observable.java:367)
at TestMergeDelayError.main(TestMergeDelayError.java:42)
1::: 4
2::: 4
onComplete
1::: 5
2::: 5
onComplete
1::: 6
2::: 6
onComplete
如您所见,只有失败的单个用户 ID 停止了他们的单独处理,但其余用户 ID 已被处理。
只是寻求建议,看看这个解决方案是否有意义,如果没有,最好的做法是什么。
谢谢,亚历克斯