当前位置: 首页 > 知识库问答 >
问题:

如何使用RxJava发出多个API请求并将其组合?

袁鸿畅
2023-03-14

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

  • 能够在某些情况下配置每个api调用的重试。我的意思是,如果我有一个重试=2,我提出3个请求,每个请求最多必须重试2次,总共最多6个请求

如果我想用一个线程发出所有请求,我需要一个异步Http客户端,不是吗?

谢谢

共有2个答案

令狐跃
2023-03-14

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

假设您有调用API的函数:

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

你想打n次电话。我假设您希望使用一系列值调用它们:

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
    }

因此,您可以从列表的元素中调用restAPI,并将结果作为列表。

另一个问题是重试。您说过要在达到单个上限时重试。这很棘手。我相信RxJava中没有现成的东西可以做到这一点。

  • 您可以使用retry(n),总共可以重试n次,但这不是您想要的。
  • 还有一个retry当{错误-

我以前没有使用过重试,但它似乎重试了整个可观察对象,这并不理想。

我的第一种方法是执行以下操作,即将每个元素的计数保存在字典或类似的内容中,并且只有在没有一个元素超过您的限制时才重试。这意味着您必须保留一个计数器,并在每次超出任何元素时进行搜索。

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

刘焱
2023-03-14

您可以使用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 -> "!");
}

在这个例子中,我们只是确认结果,但您可以检查结果并在那里执行业务逻辑,而不是这样做。

您还可以考虑合并联系

您可以在此处查看更多示例https://github.com/politrons/reactive

 类似资料:
  • 我试图通过将多个改型api调用链接在一起来创建一个可观察的api。这些步骤是: 使用api调用获取json对象列表 对于列表中的每个对象,进行另一个api调用以获取有关该项目的更多详细信息 将从这个新的详细对象中获取的数据写入磁盘上的文件(列表中的每个项目都会出现这种情况) 最后返回一个单独对象的可观察性,该对象要求为之前的每个对象创建一个文件 这是我到目前为止所拥有的: 请有人确认我使用了正确的

  • haspart(x,FruitA) HasShape(x,Round) 我检索我的个人所属的每个类(在本例中,这应该包括SpeciesA)。 我根本不确定应该使用什么:我可以使用SWRL Species(?x)^HasPart(?x,Fruit)^HasShape(?x,“$round$”)还是应该使用Reasoner?

  • 问题内容: 如何使用 java.net.URLConnection发出一个http请求? 问题答案: 首先先声明一下:发布的代码段都是基本示例。您需要处理琐碎的和,然后自己整理。 准备中 我们首先至少需要知道URL和字符集。参数是可选的,取决于功能要求。 查询参数的格式必须为,并由串联&。通常,您还可以使用指定的字符集对查询参数进行网址编码。 该只是为方便起见。当我需要String串联运算符+两次

  • 问题内容: 我读了一些将jsons发布到服务器的示例。 有人说: OkHttp是Java提供的HttpUrlConnection接口的实现。它提供用于编写​​内容的输入流,并且不知道(或不在乎)内容的格式。 现在,我想用名称和密码的参数对URL进行常规发布。 这意味着我需要自己将名称和值对编码为流? 问题答案: 当前接受的答案已过期。现在,如果您想创建一个发布请求并向其中添加参数,则应该使用Mul

  • 问题内容: 我有一个RESTful API,我已在EC2实例上使用Elasticsearch的实现公开了索引内容的语料库。我可以通过从终端机(MacOSX)运行以下命令来查询搜索: 如何使用或(不确定要使用哪个请求- 一直在使用urllib2,但听说请求更好…)将以上转换为API请求?我是否可以通过标题? 问题答案: 使用请求: 然后,根据您的API返回的响应类型,您可能需要查看或(或可能先检查)

  • 我有一个RESTful API,我在EC2实例上使用Elasticsearch实现来索引内容语料库。我可以通过从我的终端(MacOSX)运行以下命令来查询搜索: 我如何使用python/requests或python/urllib2将上述内容转换为API请求(不确定应该选择哪一个-一直在使用urllib2,但听说请求更好?我是作为标题传递还是以其他方式传递?