Rx java RxJava链接调用,有条件地结束和重试第一个调用
我需要关于如何使用RxJava完成以下任务的建议。 我需要进行一系列链式调用,如果任何调用都有包含特定值的响应,则后续调用不得发生,并且必须返回该调用的值 我正在尝试这样的事情:Rx java RxJava链接调用,有条件地结束和重试第一个调用,rx-java,Rx Java,我需要关于如何使用RxJava完成以下任务的建议。 我需要进行一系列链式调用,如果任何调用都有包含特定值的响应,则后续调用不得发生,并且必须返回该调用的值 我正在尝试这样的事情: public Observable<ReturnObject> doChainedApiCall() { Observable<ReturnObject> obs = service.apiCall1() .flatMap({ if (call1R
public Observable<ReturnObject> doChainedApiCall() {
Observable<ReturnObject> obs = service.apiCall1()
.flatMap({
if (call1Response.hasValue) {
// don't do anymore api calls, return this
ReturnObject obj = new ReturnObject();
obj.setSomething();
return Observable.just(obj);
}
return service.apiCall2();
})
.flatMap({
if (call2Response.hasValue) {
// don't do anymore api calls, return this
ReturnObject obj = new ReturnObject();
obj.setSomething();
return Observable.just(obj);
}
return service.apiCall3();
})
.flatMap({
ReturnObject obj = new ReturnObject();
return Observable.just(obj);
});
return obs;
}
service.apiCall1()
.switchIfEmpty(service.apiCall2())
.switchIfEmpty(service.apiCall3())
.defaultIfEmpty(/*maybe some default some value?*/)
public-observed-docainedapcall(){
可观测obs=service.apiCall1()
.平面图({
if(call1Response.hasValue){
//不再执行api调用,返回此
ReturnObject obj=新的ReturnObject();
对象设置某物();
返回可观察。公正(obj);
}
return service.apiCall2();
})
.平面图({
if(call2Response.hasValue){
//不再执行api调用,返回此
ReturnObject obj=新的ReturnObject();
对象设置某物();
返回可观察。公正(obj);
}
return service.apiCall3();
})
.平面图({
ReturnObject obj=新的ReturnObject();
返回可观察。公正(obj);
});
返回obs;
}
这段代码不会编译,这只是我想做的一个想法
如何确保链在第一次调用时结束并返回值(如果其中的检查为真)?假设您的
apiCallX
方法都返回一个可观察的,并且如果它们都正确完成了onCompleted
事件,您可以使用开关ifempty
和/或defaultIfEmpty
运算符。大概是这样的:
public Observable<ReturnObject> doChainedApiCall() {
Observable<ReturnObject> obs = service.apiCall1()
.flatMap({
if (call1Response.hasValue) {
// don't do anymore api calls, return this
ReturnObject obj = new ReturnObject();
obj.setSomething();
return Observable.just(obj);
}
return service.apiCall2();
})
.flatMap({
if (call2Response.hasValue) {
// don't do anymore api calls, return this
ReturnObject obj = new ReturnObject();
obj.setSomething();
return Observable.just(obj);
}
return service.apiCall3();
})
.flatMap({
ReturnObject obj = new ReturnObject();
return Observable.just(obj);
});
return obs;
}
service.apiCall1()
.switchIfEmpty(service.apiCall2())
.switchIfEmpty(service.apiCall3())
.defaultIfEmpty(/*maybe some default some value?*/)
顺便说一句,所有操作符都在列表中列出(大多数包括大理石图)。切换是正确的,但您必须编写自己的自定义操作符,在满足条件时切换,因为不存在条件。我修改了rxjava github存储库中的运算符switchifEmpty
运算符来执行此操作
import rx.*;
import rx.functions.Func1;
import rx.internal.producers.ProducerArbiter;
import rx.subscriptions.SerialSubscription;
public final class OperatorSwitchIfMatch<T> implements Observable.Operator<T, T> {
private final Observable<? extends T> alternate;
private final Func1<T, Boolean> selector ;
public OperatorSwitchIfMatch(Observable<? extends T> alternate, Func1<T, Boolean> selector) {
this.alternate = alternate;
this.selector = selector;
}
@Override
public Subscriber<? super T> call(Subscriber<? super T> child) {
final SerialSubscription ssub = new SerialSubscription();
ProducerArbiter arbiter = new ProducerArbiter();
final ParentSubscriber<T> parent = new ParentSubscriber<T>(child, ssub, arbiter, alternate,selector);
ssub.set(parent);
child.add(ssub);
child.setProducer(arbiter);
return parent;
}
private static final class ParentSubscriber<T> extends Subscriber<T> {
private boolean matched = true;
private final Subscriber<? super T> child;
private final SerialSubscription ssub;
private final ProducerArbiter arbiter;
private final Observable<? extends T> alternate;
private final Func1<T, Boolean> selector ;
ParentSubscriber(Subscriber<? super T> child, final SerialSubscription ssub, ProducerArbiter arbiter, Observable<? extends T> alternate, Func1<T, Boolean> selector) {
this.child = child;
this.ssub = ssub;
this.arbiter = arbiter;
this.alternate = alternate;
this.selector = selector;
}
@Override
public void setProducer(final Producer producer) {
arbiter.setProducer(producer);
}
@Override
public void onCompleted() {
child.onCompleted();
}
private void subscribeToAlternate() {
AlternateSubscriber<T> as = new AlternateSubscriber<T>(child, arbiter);
ssub.set(as);
alternate.unsafeSubscribe(as);
}
@Override
public void onError(Throwable e) {
child.onError(e);
}
@Override
public void onNext(T t) {
if (selector.call(t)) {
if (!child.isUnsubscribed()) {
subscribeToAlternate();
}
} else {
child.onNext(t);
}
arbiter.produced(1);
}
}
private static final class AlternateSubscriber<T> extends Subscriber<T> {
private final ProducerArbiter arbiter;
private final Subscriber<? super T> child;
AlternateSubscriber(Subscriber<? super T> child, ProducerArbiter arbiter) {
this.child = child;
this.arbiter = arbiter;
}
@Override
public void setProducer(final Producer producer) {
arbiter.setProducer(producer);
}
@Override
public void onCompleted() {
child.onCompleted();
}
@Override
public void onError(Throwable e) {
child.onError(e);
}
@Override
public void onNext(T t) {
child.onNext(t);
arbiter.produced(1);
}
}
}
导入rx.*;
导入rx.functions.Func1;
进口rx.internal.producers.producerabiter;
导入rx.subscriptions.SerialSubscription;
公共最终类运算符SwitchIfMatch实现了Observable.Operator{
私人最终观察我已经找到了我自己问题的答案
Observable<ReturnObject> observable = Observable.concat(
apiCall1(),
apiCall2(),
apiCall3()
).flatMap(response -> {
if (response.value == whatWeAreLookingFor) {
ReturnObject obj = new ReturnObject();
// set obj properties and return it.
return Observable.just(obj);
}
// Return empty to continue with next call from .concat() list.
return null; // or return Observable.empty();
}).first(); // Makes sure only the first non-empty result is called and returned.
Observable-Observable=Observable.concat(
apiCall1(),
apiCall2(),
apiCall3()
).flatMap(响应->{
if(response.value==WhatweareLooking){
ReturnObject obj=新的ReturnObject();
//设置obj属性并返回它。
返回可观察。公正(obj);
}
//返回empty以继续从.concat()列表进行下一次调用。
return null;//或return Observable.empty();
}).first();//确保只调用并返回第一个非空结果。
.first()
甚至可以替换为.firstOrDefault(Something)
,以确保在3个api调用中没有一个符合我们的要求的情况下,最终会返回一些东西
谢谢你的其他建议。我认为这种方法最简单,如果你知道一种更简单的方法来实现同样的效果,我很想知道。谢谢,尽管我实际上并不是想看看api调用响应是否为空。我只是想看看它的响应属性是否已填充。不确定你的意思,但如果我是正确的(再次查看您的代码)您从某个服务
调用了一个方法,该方法的响应将在一个单独的对象中,您必须从该对象中提取数据?这听起来像是Rx的“不正确使用”!这些方法调用的返回类型是什么(apiCallX
)?这是一个可观察的
还是什么?以及可观察的
中的元素是什么类型的?api返回的是可观察的。我基本上想看看,在每次api调用中,是否有一个“AnObject”属性是一个特定的值。如果是,就返回这个值,不要再进行api调用。而不仅仅是在每个响应上使用filter,过滤掉没有属性的项,这样你就可以得到你想要的。我试着看看它是否是一个特定的值,并且仍然将它作为新的可观察项的一部分返回。我不认为filter也会停止其余的链接api调用。我想这不是应该链接的东西…也许用rx做我想做的事情是不可能的。我是RxJava新手,老实说,你在这里做的一些事情对我来说有点高级。我有很多东西要学。一旦我理解了,如果这对我有用,我会再联系你还有更多。谢谢,通常不鼓励编写自定义运算符,因为在某些情况下,除非您是线程专家,否则您很可能会使其工作错误。我建议您提出一个更简单的解决方案。我不认为这是不鼓励的。出错很容易,但有一整节介绍如何实现您自己的cu是的,这是一个很好的方法,我认为这甚至是一个已经建立的模式。它有时也用于缓存实现a-lavalue=Observable.concat(getFromCache(),fetchFromNetwork())。first()
只有在缓存未命中的情况下才会进行网络调用。。。