wonderful world
wonderful world

Reputation: 11599

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

I use the following code in an angular app. I used the RxJS map call similar to how array map is used. After reading about RxJS switchmap operator, I'm not sure whether I should use map or switchmap. Should I use switchmap so the observable which is returned from the http call is closed so there is no memory leak?

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

Upvotes: 2

Views: 13716

Answers (3)

BizzyBob
BizzyBob

Reputation: 14750

map and switchMap have completely different purposes:

  • map - transform the shape of an emission
  • switchMap - subscribe to an observable and emit its emissions into the stream

map

Use map when you want transform the shape of each emission. Ex: emit the user name property, instead of the entire user object:

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

switchMap

Use switchMap when you want to map an emission to another observable and emit its emissions. Ex: You have an observable of some id and want to emit the resource after fetching it:

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

When user$ is subscribed to, the user returned from service.getUser(id) is emitted (not the userId string).

Upvotes: 8

Christian
Christian

Reputation: 831

switchMap is not interchangeable with the map operator, nor vise versa. Although both of them has to do with mapping (as their names suggest), they have two separate use-cases.

In your particular case, the map operator is the way to go.

When to use switchMap?

You can only use switchMap(cb) when you check all these requirements:

  1. Your callback function, cb, passed into switchMap returns an observable, observable$.

    If your cb (callback function) does not return an observable, you should look into operators that don't handle higher-level observables, such as filter and map (what you actually needed); not operators that handle higher-level observables such as concatMap and well, switchMap.

  2. You want to execute your cb sequentially before the next operation down the pipeline (after switchMap) executes.

    Maybe you want to run logic inside of cb, and optionally get the return value of cb after executing, so that you can pass it down the pipeline for further processing, for example.

  3. When you want to "discard" what will happen to cb's execution and re-execute cb every time the source observable (the thing that trickles down to switchMap(cb)) emits a new value/notification.


Applying what we hopefully learned, we know that your cb:

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

returns a plain JavaScript array; not an observable. This takes using switchMap out of the question since it violates the first requirement I made up above.

Hopefully that makes sense. :)

Upvotes: 2

Fan Cheung
Fan Cheung

Reputation: 11360

We use switchMap when the source observable is a hot observable. In which case you prefer the behaviour that cancel the succeeding observable when source emits.

In your code, you source is a one-off http call which means it will not emit multiple times and the follow up action is not executing observable but to mutate an array. There is no need to use switchMap

Upvotes: 0

Related Questions