redux-observable - difference between concat vs concatMap
Asked Answered
R

1

6

I am trying to wrap my head around the difference between concat and concatMap when using redux-observable.

In my intuition, I'm thinking that concatMap would work: - From a FAKE_LOGIN action, it will be switchMap-ed to emit FAKE_LOGIN_AUTHENTICATING action. - Inside a FAKE_LOGIN_AUTHENTICATING action, it will be concatMap-ed to emit FAKE_LOGIN_SUCCESS action, after a delay of 2 seconds.

However, the above thinking does not work. I tried all sorts of combinations and finally chanced upon the concat operator and surprisingly it works.

What is the difference between the two?

Below are my codes:

this does not work

action$.pipe(
  switchMap(
    action => of( { type: 'FAKE_LOGIN_AUTHENTICATING' } ).pipe(
      concatMap( thing => {
        return of( { type: 'FAKE_LOGIN_SUCCESS', payload: { userId: 'user-a', userData: {} } } ).pipe(
          delay( 2000 )
        );
      } )
    )
  )
);

But this does

action$.pipe(
  switchMap(
    action => of( { type: 'FAKE_LOGIN_AUTHENTICATING' } ).pipe(
      concat(
        of( { type: 'FAKE_LOGIN_SUCCESS', payload: { userId: 'user-a', userData: {} } } ).pipe(
          delay( 2000 )
        )
      )
    )
  )
);
Ruthven answered 16/1, 2019 at 11:31 Comment(0)
H
11

I think I don't understand your use-case exactly but the main difference between concatMap and concat is that concatMap accepts as a parameter a function that is invoked for every item from its source and that returns an inner Observable (it maps each item from its source to an Observable). concatMap then calls its callback only when the previous inner Observables completes.

On the other hand, concat just accepts a list of Observables and subscribes to them one after another when the previous Observable completes.

So in your case the first example just "maps" FAKE_LOGIN_AUTHENTICATING to FAKE_LOGIN_SUCCESS.

In the second example the inner block is equivalent to this:

concat(
  of({ type: 'FAKE_LOGIN_AUTHENTICATING' }),
  of({ type: 'FAKE_LOGIN_SUCCESS', payload: { userId: 'user-a', userData: {}}}).pipe(
    delay(2000),
  )
)

So it first subscribes to of({ type: 'FAKE_LOGIN_AUTHENTICATING' }) that emits and completes immediately, then subscribes to of({ type: 'FAKE_LOGIN_SUCCESS'...) that emits immediately as well and then completes.

Highfalutin answered 16/1, 2019 at 13:1 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.