在mergeMap中使用concat

时间:2018-09-28 10:42:50

标签: rxjs rxjs6

我很难理解与在concat运算符中使用mergeMap函数有关的内容。

concat的文档中说

  

您可以传递一个Observable数组,也可以将它们直接作为参数。

当我直接将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

有人知道为什么吗?这两个示例不应该完全一样吗?

1 个答案:

答案 0 :(得分:1)

这两种情况是不同的,它们不应完全相同。 concat将Observables作为参数,它将顺序地订阅这些流,并且仅在前一个Observable完成时订阅下一个Observable。每个运算符或创建方法都返回一个Observable。这意味着在第一个示例中,当您使用concat时,它将返回一个Observable,该对象发出20,然后发出24。因为您要处理嵌套的Observable,所以必须使用mergeMap,它将订阅concat返回的结果Observable。

现在在第二个示例中,如果您传递一个数组,concat会将其(内部使用from()转换为一个发出2个值的Observable,然后这些值再次成为Observables。因此,这里有3个嵌套级别。第一个是最外部的Observable,它是源of(4),第二个层次是您在mergeMap内部映射到的层次,第二个示例中的第三个层次是数组内部的Observables。问题是您只能将级别展平到2级,而不能展平到3级。同样,在您的第二个示例中,mergeMap返回的Observable发出两个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而是直接可观察到的对象:

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

两者都会打印出来:

20
24

我希望这可以使这一点更加清楚,并描述第一个示例和第二个示例之间的区别。