Javascript 地图vs concatMap

Javascript 地图vs concatMap,javascript,angular,rxjs,Javascript,Angular,Rxjs,我还没有找到这个问题的答案,但是和之间有什么区别呢?具体来说,我举了一个让我非常困惑的例子: const domainsObservable = this.auth.getAuthDomains() .shareReplay() .concatMap((authDomains) => authDomains.map((domain) => this.toDomain(domain, connectionsObservable))) .filter((authD

我还没有找到这个问题的答案,但是和之间有什么区别呢?具体来说,我举了一个让我非常困惑的例子:

const domainsObservable = this.auth.getAuthDomains()
    .shareReplay()
    .concatMap((authDomains) => authDomains.map((domain) => this.toDomain(domain, connectionsObservable)))
    .filter((authDomain) => this.isValidDomain(authDomain))
    .toArray();
这是从一个服务调用一个方法,
getAuthDomains()
,该服务刚刚返回了一个包含3个域的数组。当我使用上述实现时,我得到了一个由4个数组组成的数组,其中每个数组都有一个由3个域组成的数组。不知何故,它将响应中的数据量增加了四倍

然后,我切换到以下实现:

const domainsObservable = this.auth.getAuthDomains()
    .shareReplay()
    .map(authDomains => authDomains.map(domain => this.toDomain(domain, connectionsObservable)))
    .map(authDomains => authDomains.filter(domain => this.isValidDomain(domain)));  
这正好满足了我的需要——一个经过正确过滤的数组

那么,为什么切换到
map
会显著改变结果呢?我的行动顺序重要吗


谢谢

简单地说,这两个操作员执行以下操作:

  • map()
    -将每个值投影到一个不同的值中,该值在链的下游传播:

    .map(v => v * 2)
    
    这与
    Array.map()
    基本相同

  • concatMap()
    -将每个值投影到一个可观察值中并订阅它。操作符始终只订阅一个内部可观察对象,因此如果源可观察对象更快地发出值,它们将被缓冲在
    concatMap()

    …或者通常在角度上,您会这样做:

    .concatMap(v => this.http.get(`whatever/${v}`))
    
但有趣的部分来了。在RxJS 5中,订阅内部可观测值(从投影函数返回的可观测值等)的运算符实际上期望所谓的“可观测输入”。这意味着您可以自由地交换可观察的、承诺的、像对象一样的可观察的。。。还有JavaScript数组

在内部,它是使用
subscribeToResult
函数实现的。请注意,如果您向其传递一个数组,它将迭代该数组并分别发出每个值:

这意味着您可以使用
concatMap()。例如:

Observable.of(42)
  .concatMap(v => [1, 2, 3])
  .subscribe(console.log)
这将打印数字:

1
2
3
[1,2,3]
另一方面,如果您仅使用
map
它只需进一步传递数组:

Observable.of(42)
  .map(v => [1, 2, 3])
  .subscribe(console.log)
这将打印数字:

1
2
3
[1,2,3]
因此,
concatMap
有时仅用于解包来自源的数组,可通过
concatMap(array=>array)
观察到,这正是代码中发生的情况

哪个更好取决于你。通常,由于性能原因,在阵列对象本身上执行简单操作(如
map
filter
)比在Rx链中解包和处理更容易