angularangular5rxjs5angular-local-storage

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.


Solution

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