RXJS 按顺序链接依赖的可观察量,但获取进度条的每次发射

Bry*_*Lee 6 javascript pipe observable rxjs concatmap

我遇到了一个问题,我一直在尝试使用 找到解决方案RxJs,但似乎找不到适合它的解决方案......

  • 我有 3 个不同的 REST 请求,将按顺序调用,每个请求都需要前一个请求的响应作为参数
  • 我想实现一个进度条,当请求成功时进度条会增加

这是我的想法:

  • 我将使用管道并concatMap()避免嵌套订阅,并在前一个请求完成后订阅每个请求。

考虑这个非常简化的版本。假设每个of代表一个完整的 REST 成功请求(稍后将处理错误),并且我将使用该n参数执行未显示的工作...

const request1 = of('success 1').pipe(
  delay(500),
  tap(n => console.log('received ' + n)),
);

const request2 = (n) => of('success 2').pipe(
  delay(1000),
  tap(n => console.log('received ' + n))
);

const request3 = (n) => of('success 3').pipe(
  delay(400),
  tap(n => console.log('received ' + n))
);

request1.pipe(
  concatMap(n => request2(n).pipe(
    concatMap(n => request3(n))
  ))
)
Run Code Online (Sandbox Code Playgroud)

但是,当我订阅最后一段代码时,我只会得到最后一个请求的响应,这是预期的,因为管道解析为该响应。

因此,使用concatMap(),我可以正确链接我的依赖 REST 调用,但无法跟踪进度。

虽然我可以通过嵌套订阅轻松跟踪进度,但我正在努力避免这种情况并使用最佳实践方法。

如何链接我的依赖 REST 调用,但仍然能够在每次调用成功时执行操作?

小智 3

最简单的解决方案是拥有一个进度计数器变量,当每个响应返回时,该变量都会通过点击进行更新。

    let progressCounter = 0;

    request1.pipe(
      tap(_ => progressCounter = 0.33),
      concatMap(n => request2(n).pipe(
        tap(_ => progressCounter = 0.66),
        concatMap(n => request3(n)
          .pipe(tap(_ => progressCounter = 1)))
      ))
    );
Run Code Online (Sandbox Code Playgroud)

如果您希望进度本身是可观察的,那么您希望共享请求可观察量,以免发出重复的请求),然后将它们组合起来以获得进度。

您可能希望如何实现的示例可以在以下位置找到:https ://www.learnrxjs.io/recipes/progressbar.html