在#ngrx示例中,SwitchMap与MergeMap相对应

时间:2016-07-21 06:33:36

标签: rxjs ngrx

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

@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)
      ))
    );
}

5 个答案:

答案 0 :(得分:78)

你是对的; switchMap只要再次调用Observable函数生成新的project,就会取消订阅其project参数返回的Observable

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

mergeMap

mergeMap

图中的第一行是源Observable,它在不同时间发出(1,3,5)。图中的第二行是传递给project运算符的i => ...函数.mergeMap()返回的原型Observable。

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

switchMap

switchMap 这与switchMap()不同,project只要在新元素上再次调用它,就会取消订阅30返回的Observable。大理石图表示输出Observable中缺少第三个switchMap()项。

在您提供的示例中,这会导致取消待处理的搜索请求。这是一个非常好但很难获得的属性,通过将Http与Angular的.loginID服务返回的可取消Observable组合,您可以免费获得该属性。这可以为您节省很多麻烦,而无需担心正确处理通常在异步取消时发生的所有竞争条件。

答案 1 :(得分:6)

mergeMap

  

将每个源值投影到一个Observable,该Observable在输出Observable中合并。

     

将每个值映射到Observable,然后使用mergeAll展平所有这些内部Observable。

enter image description here

switchMap

  

将每个源值投影到一个Observable,该Observable在输出Observable中合并,仅从最近投影的Observable中发出值。

     

将每个值映射到Observable,然后使用switch展平所有这些内部Observable。

enter image description here

来源:ES6 Observables in RxJS

答案 2 :(得分:6)

你是对的。

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

这意味着当用户输入&#39; har时,ngrx会向服务发送搜索请求。当用户输入另一封信时,先前的请求将被取消(因为我们不再感兴趣了,但是&#39; harr&#39;)。

在另一个答案中提供的大理石图中非常清楚地显示出来。 在mergeMap中,以前的Observables没有被取消,因此&#39; 30&#39;和&#39; 50&#39;混在一起。使用switchMap,只会发出5s,因为3会被取消。

答案 3 :(得分:4)

它已经很详细地回答了,但是看看它,您将永远不会忘记什么是切换图

https://www.youtube.com/watch?v=rUZ9CjcaCEw

答案 4 :(得分:0)

您不希望取消API保存数据请求。这就是为什么要使用mergeMap的原因。搜索查询可以被丢弃,并且不会丢失数据,并且用户可能正在编辑其查询,而对旧查询的数据不感兴趣。因此是switchMap。