使用 angular http 模块时应该使用 map 还是 switchmap?

Should I use map or switchmap when using angular http module?

我在 angular 应用程序中使用了以下代码。我使用 RxJS map 调用类似于数组 map 的使用方式。在阅读了 RxJS switchmap 运算符之后,我不确定我应该使用 map 还是 switchmap。我应该使用 switchmap 以便关闭从 http 调用返回的可观察对象,从而不会发生内存泄漏吗?

getPeopleForTypeahead(term: string): Observable<IPersonForTypeahead[]> {

    var peopleUrl = `https://localhost:5001/api/peoplesearch?name=${term}`;

    return this.http.get<any>(peopleUrl)
      .pipe(
        map(pl => {
          return this.peopleAsFlattened(pl.peopleList).reduce((p, c) => p.concat(c));
        }),
        catchError(this.handleError('getPeopleForTypeahead', []))
      );
  }

  peopleAsFlattened = (pla: IPeopleList[]) => {
    return pla.map(pl => pl.people.map(p => {
      return {
        id: p.id,
        fullName: p.fullNames[0].firstName + " " + p.fullNames[0].lastName
      };
    }));
  }

当源 Observable 是热 Observable 时,我们使用 switchMap。在这种情况下,您更喜欢在 source 发出时取消后续 observable 的行为。

在您的代码中,您的来源是一个 one-off http 调用,这意味着它不会发出多次并且后续操作不是执行可观察的而是改变数组。不需要使用switchMap

switchMap 不能与 map 运算符互换,反之亦然。尽管它们都与映射有关(顾名思义),但它们有两个独立的 use-cases.

在您的特定情况下,map 运算符是可行的方法。

何时使用 switchMap

当您检查所有这些要求时,您只能使用 switchMap(cb)

  1. 您的回调函数 cb 传递到 switchMap return 一个可观察对象 observable$

    如果您的 cb(回调函数)没有 return 可观察值,您应该查看不处理 higher-level 可观察值的运算符,例如 filtermap(你实际需要的); not 处理 higher-level 可观察值的运算符,例如 concatMap 以及 switchMap.

  2. 您想在管道中的下一个操作(switchMap 之后)执行之前按顺序执行 cb

    也许你想运行逻辑在cb里面,有选择的在执行后得到cb的return值,这样你就可以把它传下去例如,用于进一步处理的管道。

  3. 当你想“丢弃”cb 的执行和 re-execute cb 每次源可观察时会发生什么(滴流的东西下降到 switchMap(cb)) 发出一个新的 value/notification.


应用我们希望学到的知识,我们知道您的 cb:

pl => {
    return this.peopleAsFlattened(pl.peopleList).reduce((p, c) => p.concat(c));
}

returns 一个普通的 JavaScript 数组;不是可观察的。这使使用 switchMap 成为不可能,因为它违反了我在上面提出的第一个要求。

希望这是有道理的。 :)

mapswitchMap 的用途完全不同:

  • map - 变换发射的形状
  • switchMap - 订阅一个 observable 并将其发射到流中

map

当您想要变换每个发射的形状时使用map。例如:发出用户名 属性,而不是整个用户对象:

userName$: Observable<string> = this.service.getUser(123).pipe(
    map(user => user.name)
);

switchMap

当您想要将发射映射到另一个可观察对象并发射其发射时,请使用 switchMap。例如:您有一些 id 的可观察对象,并希望在获取资源后发出资源:

user$: Observable<User> = this.userId$.pipe(
  switchMap(id => this.service.getUser(id)),
);

订阅 user$ 时,会发出从 service.getUser(id) 返回的用户( 不是用户 ID 字符串 )。