在 mergeMap 中使用 concat

Using concat inside mergeMap

我很难理解与使用 concat function inside a mergeMap 运算符相关的内容。

concat 的文档说

You can pass either an array of Observables, or put them directly as arguments.

当我将 Observables 直接作为参数时,如下例所示,我在控制台中正确地得到了 20 和 24。

of(4)
  .pipe(
    mergeMap(number => concat(of(5 * number), of(6 * number)))
  )
  .subscribe(value => console.log(value));

但是当我将它们作为数组放置时,在控制台中我得到的是 Observables 而不是它们的值:

of(4)
  .pipe(
    mergeMap(number => concat([of(5 * number), of(6 * number)]))
  )
  .subscribe(value => console.log(value));

这是 Stackblitz 中的 live version

知道这是为什么吗?两个例子不应该一样工作吗?

这两种情况不同,它们的工作方式应该不同。 concat 将 Observable 作为参数,它将顺序订阅这些流,并且仅在前一个 Observable 完成时订阅下一个 Observable。每个运算符或创建方法 return 都是一个 Observable。这意味着在第一个例子中,当你使用 concat 时,它会 return 一个发出 20 然后 24 的 Observable。因为您正在处理一个嵌套的 Observable,所以您必须使用 mergeMap,它将订阅由 concat.

生成的结果 Observable return

现在在第二个例子中,如果你传入一个数组,concat 会将它(在内部使用 from())转换为一个 Observable,它发出 2 个值,这些值又是 Observable。所以你在这里有 3 层嵌套。第一个是最外层的 Observable,源,of(4),第二个层次是你映射到你的 mergeMap 里面的那个,第二个例子中的第三个是你数组里面的 Observables。问题是你只能将级别展平到第 2 级而不是第 3 级。同样,在您的第二个示例中,由 mergeMap 编辑的 Observable return 发出两个 Observable,但它们只是代理,而不是这些 Observable 发出的值。如果你也想订阅这些,你可以像这样 mergeMap 链接到另一个

concatArray() {
  of(4)
    .pipe(
      mergeMap(number => concat([of(5 * number), of(6 * number)])),
      mergeMap(x => x)
    )
    .subscribe(value => console.log(value));
}

另一种方法是展开数组,这样concat就不会接收到ArrayLike的对象,而是直接接收Observables:

concatArray() {
  of(4)
    .pipe(
      mergeMap(number => concat(...[of(5 * number), of(6 * number)]))
    )
    .subscribe(value => console.log(value));
}

两者都会打印出来:

20
24

我希望这能让它更清楚一点,并描述第一个和第二个示例之间的区别。