RxJS 中 switchMap 与 mergeMap 的区别及正确使用姿势

· 约 7 分钟读完

前言

在 RxJS 中,switchMap 和 mergeMap 都是常用的操作符,它们都是用来处理 Observable 序列的。但是在实际使用中,我们往往会遇到选择使用哪个操作符的问题。本文将介绍 switchMap 和 mergeMap 的区别,以及在什么情况下应该使用哪个操作符,帮助读者更好地理解和使用 RxJS。

switchMap 和 mergeMap 的区别

switchMap

switchMap 的作用是将一个 Observable 序列转换成另一个 Observable 序列,并只发出最新的 Observable 序列的值。也就是说,当原始 Observable 序列发出一个新的值时,如果此时有一个正在执行的 Observable 序列,那么它将被取消,只有最新的 Observable 序列才会被发出。

例如,我们有一个搜索框,用户每输入一个字符,我们都要向服务器发送一个请求来获取搜索结果。如果用户连续输入多个字符,我们只需要发送最后一个字符所对应的请求,并忽略之前的所有请求。这时,我们可以使用 switchMap 操作符:

上面的代码中,我们使用 fromEvent 操作符从搜索框的 input 事件中创建一个 Observable 序列。然后使用 map 操作符将事件转换成搜索框的值。最后使用 switchMap 操作符将搜索框的值转换成一个 ajax 请求的 Observable 序列。这样,当用户连续输入多个字符时,只有最后一个字符所对应的 ajax 请求会被发送,之前的所有请求都会被取消。

mergeMap

mergeMap 的作用是将一个 Observable 序列转换成另一个 Observable 序列,并发出所有 Observable 序列的值。也就是说,当原始 Observable 序列发出一个新的值时,它会立即将它转换成一个 Observable 序列,并将这个新的 Observable 序列的值发出。

例如,我们有一个购物车页面,用户可以添加多个商品到购物车中。我们需要向服务器发送一个请求来获取购物车中的商品列表,并且每次添加一个新的商品都要更新购物车。这时,我们可以使用 mergeMap 操作符:

上面的代码中,我们使用 fromEvent 操作符从添加到购物车按钮的 click 事件中创建一个 Observable 序列。然后使用 map 操作符将事件转换成一个商品对象。接着使用两个 mergeMap 操作符,第一个操作符将商品对象转换成一个 ajax 请求的 Observable 序列,第二个操作符将 ajax 请求的结果转换成一个获取购物车商品列表的 Observable 序列。这样,每次添加一个商品,都会立即更新购物车列表。

正确使用姿势

在实际使用中,我们应该根据具体的场景选择使用 switchMap 或 mergeMap。下面是一些使用建议:

  1. 如果需要取消之前的操作,只保留最新的操作,应该使用 switchMap。
  2. 如果需要同时进行多个操作,并发出所有的结果,应该使用 mergeMap。
  3. 如果需要同时进行多个操作,但只关心最后一个操作的结果,可以使用 switchMap 或 exhaustMap。

除了上面的建议外,还有一些需要注意的点:

  1. switchMap 和 mergeMap 都会将原始 Observable 序列转换成一个新的 Observable 序列,因此会产生新的订阅关系。如果新的 Observable 序列产生的值也需要进行转换,应该使用管道操作符来组合多个操作符。
  2. switchMap 和 mergeMap 都可以使用第二个参数来指定并发的数量。默认情况下,它们都是不限制并发数量的。如果需要限制并发数量,可以使用 concatMap 或 mergeMapWithConcurrentLimit 操作符。

示例代码

下面是一个使用 switchMap 和 mergeMap 的完整示例代码:

上面的代码中,我们使用 fromEvent 操作符从搜索框的 input 事件中创建一个 Observable 序列。然后使用 map 操作符将事件转换成搜索框的值。接着使用 switchMap 操作符将搜索框的值转换成一个 ajax 请求的 Observable 序列。在 ajax 请求的结果中,我们使用 map 操作符将响应对象转换成响应文本,并使用 mergeMap 操作符将响应文本转换成多个结果的 Observable 序列。最后使用 map 操作符将每个结果转换成 HTML 标签。这样,我们就可以在搜索结果中显示多个结果了。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d3d0b8a941bf7134735f13