以下是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)
))
);
}
答案 0 :(得分:78)
你是对的; switchMap
只要再次调用Observable
函数生成新的project
,就会取消订阅其project
参数返回的Observable
。
RxJs非常强大且密集,但其高级抽象有时会使代码难以理解。让我揭穿@Andy Hole给出的大理石图表和文档,并让它们更新。你可能会发现marble syntax reference非常有价值,可以更好地理解他们的测试中的rxjs运算符(至少我发现这个缺失/ official docs中没有突出显示。)
图中的第一行是源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()
不同,project
只要在新元素上再次调用它,就会取消订阅30
返回的Observable。大理石图表示输出Observable中缺少第三个switchMap()
项。
在您提供的示例中,这会导致取消待处理的搜索请求。这是一个非常好但很难获得的属性,通过将Http
与Angular的.loginID
服务返回的可取消Observable组合,您可以免费获得该属性。这可以为您节省很多麻烦,而无需担心正确处理通常在异步取消时发生的所有竞争条件。
答案 1 :(得分:6)
将每个源值投影到一个Observable,该Observable在输出Observable中合并。
将每个值映射到Observable,然后使用mergeAll展平所有这些内部Observable。
将每个源值投影到一个Observable,该Observable在输出Observable中合并,仅从最近投影的Observable中发出值。
将每个值映射到Observable,然后使用switch展平所有这些内部Observable。
答案 2 :(得分:6)
你是对的。
如您所见,switchMap与搜索功能一起使用。此示例中的搜索框被编程为在用户在文本框中输入文本时(基本上发出350ms去抖或延迟)发出搜索请求。
这意味着当用户输入&#39; har时,ngrx会向服务发送搜索请求。当用户输入另一封信时,先前的请求将被取消(因为我们不再感兴趣了,但是&#39; harr&#39;)。
在另一个答案中提供的大理石图中非常清楚地显示出来。 在mergeMap中,以前的Observables没有被取消,因此&#39; 30&#39;和&#39; 50&#39;混在一起。使用switchMap,只会发出5s,因为3会被取消。
答案 3 :(得分:4)
它已经很详细地回答了,但是看看它,您将永远不会忘记什么是切换图
答案 4 :(得分:0)
您不希望取消API保存数据请求。这就是为什么要使用mergeMap的原因。搜索查询可以被丢弃,并且不会丢失数据,并且用户可能正在编辑其查询,而对旧查询的数据不感兴趣。因此是switchMap。