3
votes

I'm using Angular2 with @ngrx/store & effects... I have an authenticate effect like this

@Effect() authenticate$ = this.updates$
  .whenAction(AuthActions.AUTHENTICATE_REQUEST)
  .switchMap(update => this.api.post('/authenticate', update.action.payload)
  // somehow use data in the original `update` to work out if we need to
  // store the users credentials after successful api auth call
    .map((res:any) => this.authActions.authenticateSuccess(res.json()))
    .catch((err:any) => Observable.of(this.authActions.authenticateError(err)))
)

Within the update.action.payload object is a rememberMe flag. So... if set to true i need to store the credentials in a LocalStorage service AFTER the api request has returned successfully... but obviously not if there is an error.

How can this be achieved as inside the switchMap operator we only have access to the result of the api post call?


WORKING CODE FROM ANSWER BELOW

@Effect() authenticate$ = this.updates$
.whenAction(AuthActions.AUTHENTICATE_REQUEST)
.switchMap(update => this.api.post('/authenticate', update.action.payload)
  .map((res:any) => {
    return {
      res: res,
      update: update
    };
  })
  .do((result:any) => {
    if(result.update.action.payload.remember) {
      this.authService.setAuth(result.res.json());
    }
  })
  .map((result:any) => this.authActions.authenticateSuccess(result.res.json()))
  .catch((err:any) => Observable.of(this.authActions.authenticateError(err)))
);
1
I can think of one or two ways to do this, but they're going to be hacky. The cleanest way (IMHO) is going to be to have the rememberMe field come back in the API response - is that possible for you?drew moore
That'd definitely be the cleanest but unfortunately I don't have control of what backend returns..markstewie

1 Answers

3
votes

You should be able to map the post observable to include update:

@Effect() authenticate$ = this.updates$
  .whenAction(AuthActions.AUTHENTICATE_REQUEST)
  .switchMap(update => this.api.post('/authenticate', update.action.payload).map((res:any) => {
    return {
      res: res,
      update: update
    };
  }))
  .do((result:any) => { ... whatever it is you need to do with result.update ... })
  .map((result:any) => this.authActions.authenticateSuccess(result.res.json()))
  .catch((err:any) => Observable.of(this.authActions.authenticateError(err)))
)