Rx java RxJava链接调用,有条件地结束和重试第一个调用

Rx java RxJava链接调用,有条件地结束和重试第一个调用,rx-java,Rx Java,我需要关于如何使用RxJava完成以下任务的建议。 我需要进行一系列链式调用,如果任何调用都有包含特定值的响应,则后续调用不得发生,并且必须返回该调用的值 我正在尝试这样的事情: public Observable<ReturnObject> doChainedApiCall() { Observable<ReturnObject> obs = service.apiCall1() .flatMap({ if (call1R

我需要关于如何使用RxJava完成以下任务的建议。 我需要进行一系列链式调用,如果任何调用都有包含特定值的响应,则后续调用不得发生,并且必须返回该调用的值

我正在尝试这样的事情:

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-la
value=Observable.concat(getFromCache(),fetchFromNetwork())。first()
只有在缓存未命中的情况下才会进行网络调用。。。