在实际项目中使用 Rxjs mergeMap 的经验分享

举报
汪子熙 发表于 2022/11/24 11:24:17 2022/11/24
【摘要】 本文介绍笔者在实际 Angular 开发项目中对 Rxjs 里 mergeMap 这个 Operator 的使用经验分享。注意:flatMap 是 mergeMap 的别名。如果一次只能激活一个内部订阅,请使用 switchMap.如果内部 observables 的发射和订阅顺序很重要,请使用 concatMap.当需要展平内部 observable 但想要手动控制内部订阅的数量时,是 m...

本文介绍笔者在实际 Angular 开发项目中对 Rxjs 里 mergeMap 这个 Operator 的使用经验分享。

注意:

  1. flatMap 是 mergeMap 的别名。
  2. 如果一次只能激活一个内部订阅,请使用 switchMap.
  3. 如果内部 observables 的发射和订阅顺序很重要,请使用 concatMap.

当需要展平内部 observable 但想要手动控制内部订阅的数量时,是 mergeMap 极佳的使用场合。

例如,当使用 switchMap 时,每个内部订阅在源发出时完成,即任意时间段只允许一个活动的内部订阅。相比之下,mergeMap 允许同时激活多个内部订阅。因此,mergeMap 最常见的用例之一是不应取消的请求,这些请求被认为是写入而不是读取。

一个典型的例子就是 SAP 电商云购物车里不同行项目的金额,可以并行地进行增减操作。

请注意,如果这些写入必须保持顺序,则 concatMap 是更好的选择。比如数据库的写操作。

由于 mergeMap 一次维护多个活动的内部订阅,因此可能会由于长期存在的内部订阅造成内存泄漏。一个基本的例子是,如果使用内部计时器或 dom 事件流映射到可观察对象。在这些情况下,如果仍然希望使用 mergeMap,一个好办法是利用另一个运算符来管理内部订阅的完成,比如考虑 take 或 takeUntil。当然还可以使用 concurrent 参数限制一次活动内部订阅的数量。

看一个例子:

import { fromEvent, of } from 'rxjs';
import { mergeMap, delay } from 'rxjs/operators';

// faking network request for save
const saveLocation = location => {
  return of(location).pipe(delay(500));
};
// streams
const click$ = fromEvent(document, 'click');

click$
  .pipe(
    mergeMap((e: MouseEvent) => {
      return saveLocation({
        x: e.clientX,
        y: e.clientY,
        timestamp: Date.now()
      });
    })
  )
  // Saved! {x: 98, y: 170, ...}
  .subscribe(r => console.log('Saved!', r));

saveLocation 是一个函数,它能把任何传入的输入参数,包裹成一个 Observable,并且这个 Observable 并不是立即 emit 数据,而是延迟 500 毫秒。

mergeMap 接收一个函数作为输入参数,这个函数的输入参数就是通过 pipe 链接 mergeMap 的 Observable 里包含的元素,即 MouseEvent;project 返回的数据类型是一个新的 Observable,包含了屏幕点击的 X 和 Y 坐标以及当前时间戳。

最后产生的输出:

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。