首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >#ngrx示例中的SwitchMap与MergeMap

#ngrx示例中的SwitchMap与MergeMap
EN

Stack Overflow用户
提问于 2016-07-21 14:33:36
回答 4查看 34.5K关注 0票数 60

下面是Ngrx示例的代码:https://github.com/ngrx/example-app/blob/master/src/effects/book.ts我的问题是,为什么在第一个@Effect中,它使用switchMap,而其他@Effect使用mergeMap。这是不是因为第一个@Effect是处理网络,并且如果switchMap正在运行,您可以取消之前的网络请求?

代码语言:javascript
运行
复制
@Effect() search$ = this.updates$
    .whenAction(BookActions.SEARCH)
    .map<string>(toPayload)
    .filter(query => query !== '')
    .switchMap(query => this.googleBooks.searchBooks(query)
      .map(books => this.bookActions.searchComplete(books))
      .catch(() => Observable.of(this.bookActions.searchComplete([])))
    );


  @Effect() clearSearch$ = this.updates$
    .whenAction(BookActions.SEARCH)
    .map<string>(toPayload)
    .filter(query => query === '')
    .mapTo(this.bookActions.searchComplete([]));


  @Effect() addBookToCollection$ = this.updates$
    .whenAction(BookActions.ADD_TO_COLLECTION)
    .map<Book>(toPayload)
    .mergeMap(book => this.db.insert('books', [ book ])
      .mapTo(this.bookActions.addToCollectionSuccess(book))
      .catch(() => Observable.of(
        this.bookActions.addToCollectionFail(book)
      ))
    );


  @Effect() removeBookFromCollection$ = this.updates$
    .whenAction(BookActions.REMOVE_FROM_COLLECTION)
    .map<Book>(toPayload)
    .mergeMap(book => this.db.executeWrite('books', 'delete', [ book.id ])
      .mapTo(this.bookActions.removeFromCollectionSuccess(book))
      .catch(() => Observable.of(
        this.bookActions.removeFromCollectionFail(book)
      ))
    );
}
EN

回答 4

Stack Overflow用户

发布于 2017-02-14 21:24:48

您是对的;一旦switchMap再次调用project函数以生成新的Observable,它就会取消订阅由其project参数返回的project

RxJs非常强大和密集,但它的高级抽象有时会使代码难以理解。让我来揭穿@Andy Hole给出的大理石图表和文档,并更新它们。您可能会发现marble syntax reference对于从测试中更好地理解rxjs运算符非常有价值(至少我发现这一点在official docs中缺失/不够突出)。

mergeMap

图中的第一条线是在不同时间发射(1,3,5)的源可观测值。图中的第二行是由传递给.mergeMap()操作符的project函数i => ...返回的原型可观察对象。

当源可观察对象发出项1时,mergeMap()将使用i=1调用project函数。返回的可观察对象将每10帧发出三次10 (参见marble syntax reference)。当源可观测对象发出项3,并且project函数创建一个发出30三次的可观测对象时,也会发生同样的情况。请注意,mergeMap()的结果包含从project返回的每个观察值生成的所有三个元素。

switchMap

这与switchMap()不同,一旦在新元素上再次调用project返回的Observable,它将取消订阅该Observable。大理石图表明了这一点,输出可观测中缺少第三个30项。

在您给出的示例中,这会导致挂起的搜索请求被取消。这是一个非常好但很难获得的属性,您可以通过将switchMap()与Angular的Http服务返回的cancellable Observables结合使用来免费获得该属性。这可以为您省去很多麻烦,而不必担心如何正确处理异步取消通常会出现的所有竞争条件。

票数 100
EN

Stack Overflow用户

发布于 2016-09-22 17:23:28

你是正确的。

如您所见,switchMap与搜索功能一起使用。本例中的搜索框被编程为基本上在用户在文本框中输入文本时发出搜索请求(具有350ms的去抖动或延迟)。

这意味着当用户输入'har‘时,ngrx会向服务发送一个搜索请求。当用户输入另一个字母'r‘时,前一个请求被取消(因为我们对'har’不再感兴趣,而对‘harr’感兴趣)。

在另一个答案中提供的大理石图中很好地显示了这一点。在mergeMap中,以前的观测值没有被取消,因此“30”和“50”混合在一起。使用switchMap时,只发射5,因为取消了3。

票数 7
EN

Stack Overflow用户

发布于 2016-07-27 23:58:50

mergeMap

将每个源值投影到一个可观测对象,该可观测对象被合并到输出可观测对象中。

将每个值映射到一个可观察对象,然后使用mergeAll展平所有这些内部可观察对象。

switchMap

将每个源值投影到一个可观测值,该可观测值被合并到输出可观测值中,仅从最近投影的可观测值发出值。

将每个值映射到一个可观察对象,然后使用switch展平所有这些内部可观察对象。

来源:ES6 Observables in RxJS

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38496604

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档