0

I saw this line of code :

this.http.get(`/payments`).pipe(
      mergeMap((payments) => {
        return of(payments);
      }),
    );

is it as same as this (if so, why its written that way?):

this.http.get(`/payments`)
yaya
  • 7,675
  • 1
  • 39
  • 38

4 Answers4

3

Let's see it in action

const httpCall = rxjs.of('payment');

httpCall.pipe(
  rxjs.operators.mergeMap(v => rxjs.of(v))
).subscribe(v => console.log(v));
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.3/rxjs.umd.js"></script>

So basically, it does nothing.

2
this.http.get(`/payments`).pipe(
      mergeMap((payments) => of(payments)),
);

For each, emitted value the mergeMap() operator creates a new observable of that value, and then the operator subscribes to that new observable. Each value emitted by that observable is forwarded to the subscriber until the inner observable completes.

This is repeated for each emitted value from the source observable.

There is no delay or multicasting taking place here since the of(payments) will emit the value in the same JavaScript call stack.

You can replace the mergeMap with a switchMap() and it would also have no effect.

The source code is most likely remnants of someone's attempt to debug or modify the values emitted, and since http.get() emits a single value it doesn't matter if you used mergeMap or switchMap in this case. The majority of people who use these operators with a HTTP call is to chain to another HTTP call.

If you need to chain to other HTTP calls, then take a look at my switchChain() operator that included in my observables library.

https://github.com/reactgular/observables

Reactgular
  • 52,335
  • 19
  • 158
  • 208
  • Shameless self promoting ... Meh. Also, I don't know about other frameworks/libraries, but I think [this operator](https://github.com/ngneat/until-destroy) would make a great addition to your library for Angular ! –  Oct 02 '19 at 11:29
  • @Maryannah thanks, I've used that library. It's very clever, but there are edge cases where it doesn't work. I made a destroyable base class library instead. https://github.com/reactgular/destroyable We have to promote stuff, because no one notices it otherwises :) – Reactgular Oct 02 '19 at 11:31
  • `The source code is most likely remnants of someone's attempt to modify the values emitted` i think so as well. probably developer wanted to have a blueprint to change modify values later (in next versions). cause in other places in the source code (similar to this) , developer modifed the values already. thanks for answer. – yaya Oct 02 '19 at 11:33
  • Yeah I'm not a fan of the required `super()` when you `extend` ... But the library I provided recently offered the class decorator to prevent the famous not existing `ngOnDestroy` edge case ! And I agree on the idea, but I'm not sure SOF is the public you want to target ... –  Oct 02 '19 at 11:34
  • @Maryannah an alternative is to take a ViewRef in the constructor, and hook into the view destroy callback instead of requiring `super.ngOnDestroy()`. A dev would need to pass that, but you get TypeScript compiler errors if you forgot. It's far less likely a dev would make a mistake in that case. I might make that change in a v2 update. – Reactgular Oct 02 '19 at 11:43
1

According to the documentation of RxJS:

This operator is best used when you wish to flatten an inner observable but want to manually control the number of inner subscriptions. For instance, when using switchMap each inner subscription is completed when the source emits, allowing only one active inner subscription. In contrast, mergeMap allows for multiple inner subscriptions to be active at a time. Because of this, one of the most common use-case for mergeMap is requests that should not be canceled, think writes rather than reads. Note that if order must be maintained concatMap is a better option.

This basically means that in case you have several subscriptions to this observable you will still have a single call to the API as these subscriptions are managed internally.

  • In case of a single subscription there is no difference
Alon Yampolski
  • 851
  • 7
  • 15
1

There probably was some kind of request chaining like:

this.http.get(`/payments`).pipe(
  mergeMap(response => this.http.post(`/audit`, response.id)),
  map(secondResponse => {})
)

but eventually got changed to a single http call.

mergeMap or flatMap can be used to flatten the Observables (to convert an Observable of Observable to a single Observable)

So the answer is yes - changing to this.http.get('/payments') will not change the behavior at all.

Yevhenii Dovhaniuk
  • 1,073
  • 5
  • 11