【问题标题】:Using RxJS for unknown number of consequtive HTTP Requests使用 RxJS 处理未知数量的后续 HTTP 请求
【发布时间】:2023-03-09 08:32:01
【问题描述】:

我需要从我们的 API 中获取大量数据点。

但是这些不能一次全部获取,因为响应时间太长,所以我想把它分成多个请求。响应如下所示:

{
  href: www.website.com/data?skip=0&limit=150,
  nextHref: www.website.com/data?skip=150&limit=150,
  maxCount: 704,
  skip: 0,
  count: 150,
  limit:150,
  results: [...]
}

所以,最终我需要不断地调用nextHref,直到我们真正到达最后一个。

在每次请求之后,我想获取结果并将它们连接成一个数据列表,该列表将在 UI 上更新。

我对 Obervables 世界比较陌生,但想用 RxJS 创建一个解决方案。有没有人知道如何实现这个?

最让我感动的部分是我不知道我必须提前完成多少请求。它只需要一直循环直到完成。

【问题讨论】:

  • 这可能会对您有所帮助 stackoverflow.com/a/66278720/7177558 。如果这个答案还不够,请联系我,我将创建一个与您的情况完全匹配的 stackblitz。
  • 使用 RxJS 扩展操作符应该很简单
  • 这可以在纯 javascript 中使用 async/await 轻松完成

标签: javascript rxjs


【解决方案1】:

您似乎可以确定在收到第一个响应后要拨打的电话次数。因此,我们可以进行第一次调用,并构建一个 observable,它返回“第一次调用”的结果以及所有后续调用的结果。

我们可以使用scan 将结果累加到一个数组中。

const results$ = makeApiCall(0, 150).pipe(
  switchMap(firstResponse => {
    const pageCount = Math.ceil(firstResponse.maxCount / firstResponse.limit);
    const pageOffsets = Array(pageCount - 1).fill(0).map((_, i) => (i + 1) * firstResponse.limit);

    return concat(
      of(firstResponse),
      from(pageOffsets).pipe(
        mergeMap(offset => makeApiCall(offset, firstResponse.limit), MAX_CONCURRENT_CALLS)
      )
    );
  }),
  scan((acc, cur) => acc.concat(cur.results), [])
);

以下是其作用的细分:

  • 我们首先致电makeApiCall(),以便确定需要拨打多少其他电话
  • from 创建一个 observable,它每次发出一个 offsets 数组
  • mergeMap 将使用传入的偏移量执行我们对makeApiCall() 的后续调用并发出结果。请注意,您可以提供“并发”限制,以控制一次调用的数量。
  • concat 用于返回一个发出第一个响应的可观察对象,然后是后续调用的结果
  • switchMap 订阅这个内部 observable 并发出结果
  • scan 用于将结果累加到单个数组中

这是一个有效的 StackBlitz 演示。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-26
    • 1970-01-01
    • 2021-05-23
    • 1970-01-01
    • 2019-11-20
    • 1970-01-01
    • 2018-01-07
    • 2017-12-19
    相关资源
    最近更新 更多