【问题标题】:Notify when Sequence of Observables Complete当 Observables 序列完成时通知
【发布时间】:2019-05-11 20:15:21
【问题描述】:

我正在尝试使用 RxJS Observables 根据用户选择过滤对象列表。要获取过滤对象列表,我需要依次调用三个单独的服务,并将前一个服务的值传递给后续服务。

注意 1:这三个服务中的每一个都返回 Observable

注意 2:每个服务可以返回任意数量的结果,每个结果都需要传递给下一个服务。

只有在第三个服务完成发射所有值之后,我的代码才能正常继续。

这是我现在拥有的:

this.firstService.getFirstResults(filterOption)
            .subscribe(firstResult => this.secondService.getSecondResults(firstResult)
                .subscribe(secondResult => this.thirdService.getThirdResults(secondResult)
                    .subscribe(thirdResult => this.processResult(thirdResult, firstResult),
                    null,
                    () => console.log("COMPLETE")))
            );

上面的代码对我来说几乎是完美的。最后,processResult() 函数正确地构建了一个包含所有过滤对象的数组。

但是,当 Observables 序列真正完成时,我不知道如何获得通知。我曾希望第三个服务的 complete 部分能完成这项工作,但它会多次打印到控制台而不是一次。

注意 3: 在对 processResult() 的最终调用中,我需要同时传递从 firstService.getFirstResults() 返回的 thirdResult 值以及相应的 firstResult 值。

【问题讨论】:

  • 使用 switchMap() 或 mergeMap() 或 concatMap() 运算符(取决于您真正想要的)。既然你需要第一个发出的值来调用第二个,它们怎么能并行运行?
  • 抱歉,并行是一个错误的选择。我想我的意思是异步。刚刚编辑帖子进行更正。
  • 您能否提供一个代码 sn-p,说明如何将上面的代码转换为使用 switchMap 或 mergeMap?我自己试过这个,认为它可以解决我的问题,但最终的过滤器数组从未构建,COMPLETE 控制台日志也从未打印过。在线查找示例代码时,大多数似乎都演示了不带参数或静态参数的函数序列。
  • gist.github.com/jnizet/aeb37e62a059c99f2bb43f19d0b82e4a。但是你的 observable 只有在所有 observable 都完成时才会完成(在 mergeMap 的情况下)
  • 感谢 sn-p,因为我现在似乎正在取得进展。我唯一剩下的问题似乎是我错误地将filterOption变量作为processResult()函数的第二个参数,而实际上它应该是firstService返回的值,例如``processResult(thirdResult, firstResult)@987654330调用该函数后,@firstResult` 变量将不可见。有什么想法吗?

标签: typescript rxjs observable


【解决方案1】:

switchMap提供了第二个参数来重构返回值,下面是demo演示如何做。

function getResult(filterOption) {
  return this.firstService.getFirstResult(filterOption).pipe(
    switchMap(
      firstResult => this.secondeService.getSecondResult(firstResult),
      ([firstResult, secondResult]) => ({ firstResult, secondResult }),
    ),
    switchMap(
      ({ secondResult }) => this.thirdService.getThirdResult(secondResult),
      ([{ firstResult }, thirdResult]) => ({ firstResult, thirdResult }),
    ),
  );
}

getResult(filterOption).subscribe({
  next: ({ firstResult, thirdResult }) => this.processResult(thirdResult, firstResult),
  completed: () => console.log('completed'),
});

【讨论】:

  • 感谢你们俩。我现在可以使用 mergeMap 运算符正常工作。由于我使用的是 TypeScript 而不是 JavaScript,因此必须将它们全部组合到一个函数中以用于范围界定,但它在其他方面与上面对我有用的代码基本相同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-14
  • 2010-12-01
相关资源
最近更新 更多