Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 5 RxJs concatMap,switchMap,mergeMap which?

I have this method to get token via localstorage, if token is not exist or is expired, I will call API to get another token and store to localstorage.

In this case, which map should I use, currently using mergeMap, or other way to do this?

public doGetToken():Observable<Token> {
    return this.loadToken().pipe( //get via localstorage
      map(token=>{
        let valid = this.validateTokenIsValid(token);
        let data = {
          token: token,
          valid: valid
        };
        return data;
      }),
      mergeMap(data=>{
        if (!data.valid) {
          return this.doApiGetToken(data.token).pipe(
            map(
              token=>{
                this.saveToken(token); //save to localstorage
                return token;
              }
            )
          );
        } else {
          return of(data.token);
        }
      })
    );

version: Angular 5, rxjs5

Thank you in advance.

like image 392
Sola Avatar asked Sep 03 '25 06:09

Sola


2 Answers

If you only make one request, then it doesn't matter which map you use.

mergeMap (also called flatMap), concatMap , exhaustMap or switchMap will behave the same.

These operators behave differently when you emit more than 1 value:

switchMap

will apply the mapping to the latest input received:

Src : -----A----B----C--D-E-------

switchMap (x => x--x) // emit x twice when received

Out:  ------A--A-B--B-C-D-E--E----

concatMap

will finish the mapping before taking another input:

Src : -----A----B----C--D-E-----------

concatMap (x => x--x) // emit x twice when received

Out:  ------A--A-B--B-C--C--D--D-E--E

mergeMap

is like concatMap, but it doesn't wait for mapping to complete. The results can overlap though:

Src : -----A----B----C-D---E-----------

mergeMap (x => x--x) // emit x twice when received

Out:  ------A--A-B--B-C-D-C-D-E--E-----

exhaustMap

is like a reversed switchMap, it gives priority to the output:

Src : -----A--------B----C-D---E-----------

exhaustMap (x => x--x--x) // emit x thrice when received

Out:  ------A--A--A--B--B--B-D--D--D-------

For more information :

https://medium.com/@vdsabev/the-simple-difference-between-rxjs-switchmap-and-mergemap-397c311552a5

Marble diagrams :

http://rxmarbles.com/#mergeMap

Edit : I moved the simplification of your code to the bottom to make the general information visible at first sight.

public doGetToken(): Observable<Token> {
  return this.loadToken()
    .pipe( //get via localstorage
      mergeMap(token => {
        if(!this.validateTokenIsValid(token))
          return of(token)
        return this.doApiGetToken(token)
          .pipe(
            tap( token => this.saveToken(token)) //save to localstorage
          );
      })
    )
};
like image 199
madjaoue Avatar answered Sep 04 '25 22:09

madjaoue


single source observables the above operators does not differ.

switchMap: emits values and is only interested in the very last one it sent. All the responses of the calls before get ignored.

concatMap: behaves like a queue: It stores all calls and sends one after another. If one is completed, the next one is being processed.

mergeMap: Also sends all requests, like concatMap but does not wait until the response is coming back. It sends them out as they come. But it receives every response and does not ignore something. The order here is not guaranteed.

exhaustMap: Emits the first request and ignores all future requests until the first one gets back. Then it is ready for a new one.

Please refer this link. really great one

https://offering.solutions/blog/articles/2021/03/08/switchmap-mergemap-concatmap-exhaustmap-explained/

like image 40
pa1 Raju Avatar answered Sep 04 '25 22:09

pa1 Raju