Asynchronous 如何使用RxJava发出多个API请求并将它们组合起来?

Asynchronous 如何使用RxJava发出多个API请求并将它们组合起来?,asynchronous,rx-java,observable,nonblocking,rx-java2,Asynchronous,Rx Java,Observable,Nonblocking,Rx Java2,我必须进行N个REST API调用并合并所有调用的结果,或者如果至少有一个调用失败(返回错误或超时),则失败。 我想使用RxJava,我有一些要求: 能够在某些情况下配置每个api调用的重试。我的意思是,如果我有一个retry=2,我提出3个请求,每个请求最多要重试2次,总共最多6个请求 快失败!如果一个API调用失败了N次(其中N是重试的配置),剩余的请求是否没有结束并不重要,我想返回一个错误 如果我想用一个线程发出所有请求,我需要一个异步Http客户端,不是吗 谢谢。您可以使用Zip操作

我必须进行N个REST API调用并合并所有调用的结果,或者如果至少有一个调用失败(返回错误或超时),则失败。 我想使用RxJava,我有一些要求:

  • 能够在某些情况下配置每个api调用的重试。我的意思是,如果我有一个retry=2,我提出3个请求,每个请求最多要重试2次,总共最多6个请求
  • 快失败!如果一个API调用失败了N次(其中N是重试的配置),剩余的请求是否没有结束并不重要,我想返回一个错误
如果我想用一个线程发出所有请求,我需要一个异步Http客户端,不是吗


谢谢。

您可以使用
Zip
操作符在请求结束后将所有请求压缩到一起,并在那里检查是否所有请求都成功

 private Scheduler scheduler;
private Scheduler scheduler1;
private Scheduler scheduler2;

/**
 * Since every observable into the zip is created to subscribeOn a different thread, it´s means all of them will run in parallel.
 * By default Rx is not async, only if you explicitly use subscribeOn.
 */
@Test
public void testAsyncZip() {
    scheduler = Schedulers.newThread();
    scheduler1 = Schedulers.newThread();
    scheduler2 = Schedulers.newThread();
    long start = System.currentTimeMillis();
    Observable.zip(obAsyncString(), obAsyncString1(), obAsyncString2(), (s, s2, s3) -> s.concat(s2)
            .concat(s3))
            .subscribe(result -> showResult("Async in:", start, result));
}

private Observable<String> obAsyncString() {
    return Observable.just("Request1")
            .observeOn(scheduler)
            .doOnNext(val -> {
                System.out.println("Thread " + Thread.currentThread()
                        .getName());
            })
            .map(val -> "Hello");
}

private Observable<String> obAsyncString1() {
    return Observable.just("Request2")
            .observeOn(scheduler1)
            .doOnNext(val -> {
                System.out.println("Thread " + Thread.currentThread()
                        .getName());
            })
            .map(val -> " World");
}

private Observable<String> obAsyncString2() {
    return Observable.just("Request3")
            .observeOn(scheduler2)
            .doOnNext(val -> {
                System.out.println("Thread " + Thread.currentThread()
                        .getName());
            })
            .map(val -> "!");
}
私有调度程序;
专用调度器调度器1;
专用调度程序2;
/**
*由于zip中的每个可观察对象都是在不同的线程上创建的,这意味着它们都将并行运行。
*默认情况下,只有在显式使用subscribeOn时,Rx才是异步的。
*/
@试验
public-void-testAsyncZip(){
scheduler=Schedulers.newThread();
scheduler1=Schedulers.newThread();
scheduler2=Schedulers.newThread();
长启动=System.currentTimeMillis();
obaservable.zip(obAsyncString(),obAsyncString1(),obAsyncString2(),(s,s2,s3)->s.concat(s2)
康卡特先生(s3))
.subscribe(结果->显示结果(“异步输入:”,开始,结果));
}
私有可观测的obAsyncString(){
可观察的返回。仅(“请求1”)
.observeOn(调度程序)
.doOnNext(val->{
System.out.println(“Thread”+Thread.currentThread()
.getName());
})
.map(val->“你好”);
}
私有可观测obAsyncString1(){
可观察的返回。仅(“请求2”)
.observeOn(附表1)
.doOnNext(val->{
System.out.println(“Thread”+Thread.currentThread()
.getName());
})
.地图(val->“世界”);
}
私有可观测obAsyncString2(){
可观察的返回。仅(“请求3”)
.observeOn(附表2)
.doOnNext(val->{
System.out.println(“Thread”+Thread.currentThread()
.getName());
})
.地图(val->“!”);
}
在本例中,我们只是查看结果,但您可以检查结果并在那里执行业务逻辑,而不是这样做

也可以考虑<代码>合并<代码>或<代码>联系人< /代码>。


您可以在这里查看更多示例

我建议使用
可观察的
来包装所有调用

假设您拥有调用API的函数:

fun restAPIcall(request: Request): Single<HttpResponse>

不需要创建多个
调度程序。newThread()
。它为创建的每个工作线程创建一个新线程,因此只需重用同一个调度程序就会得到相同的结果。
val valuesToSend: List<Request>

Observable
    .fromIterable(valuesToSend)
    .flatMapSingle { valueToSend: Request ->
        restAPIcall(valueToSend)
    }
    .toList() // This converts: Observable<Response> -> Single<List<Response>>
    .map { responses: List<Response> -> 
        // Do something with the responses
    }
val counter = valuesToSend.toMap()

yourObservable
    .map { value: String ->
        counter[value] = counter[value]?.let { it + 1 }?: 0 // Update the counter
        value // Return again the value so you can use it later for the api call
    }
    .map { restAPIcall(it) }
    // Found a way to take yourObservable and readd the element if it doesn't exceeds
    // your limit (maybe in an `onErrorResumeNext` or something). Else throw error