map vs concatMap

Use*_*842 5 javascript rxjs angular

我一直无法找到这个问题的答案,但是concat地图地图有什么区别?具体来说,我有一个例子让我很困惑:

const domainsObservable = this.auth.getAuthDomains()
    .shareReplay()
    .concatMap((authDomains) => authDomains.map((domain) => this.toDomain(domain, connectionsObservable)))
    .filter((authDomain) => this.isValidDomain(authDomain))
    .toArray();
Run Code Online (Sandbox Code Playgroud)

这是从服务调用一个方法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)));  
Run Code Online (Sandbox Code Playgroud)

这给了我我所需要的 - 一个正确过滤的单个数组.

那么为什么要切换到map显着改变结果呢?我的操作顺序是否重要?

谢谢

mar*_*tin 6

简单地说,这两个运营商做了以下事情:

但这里有趣的部分.在RxJS 5中,订阅内部Observables(从投影函数返回的Observable等)的运算符实际上期望所谓的"可观察输入".这意味着您可以自由地交换Observables,Promises,Observables类对象......以及JavaScript数组.

在内部,它是使用该subscribeToResult功能实现的.请注意,如果您传递一个数组,它将迭代它并单独发出每个值:https://github.com/ReactiveX/rxjs/blob/master/src/internal/util/subscribeToResult.ts#L17

这意味着您可以使用concatMap()"解包"阵列到单个发射.例如:

Observable.of(42)
  .concatMap(v => [1, 2, 3])
  .subscribe(console.log)
Run Code Online (Sandbox Code Playgroud)

这将打印数字:

1
2
3
Run Code Online (Sandbox Code Playgroud)

另一方面,如果你只使用map它,它将简单地传递数组:

Observable.of(42)
  .map(v => [1, 2, 3])
  .subscribe(console.log)
Run Code Online (Sandbox Code Playgroud)

这将打印数字:

[1,2,3]
Run Code Online (Sandbox Code Playgroud)

因此concatMap,有时只用于解压缩来自Observable源的数组concatMap(array => array),这正是代码中正在发生的事情.

哪一个更好取决于你.通常,它更容易执行像简单的操作mapfilter数组对象本身,而不是开箱和处理在Rx链性能的原因上.