1
votes

I'm writing a service in Angular 5 (RxJs 5.5.1) and I have the following scenario where I'm trying to implement a login workflow.

...
signInBasic(user: string, pwd: string): Observable<AuthenticationStatus> {
    return this.http.post('some_url', params, { observe: 'response', responseType: 'text' })
      .map((response: HttpResponse<Object>) => {
        this.status = response.status === 200 ? AuthenticationStatus.Authenticated : AuthenticationStatus.NotAuthenticated;
        return this.status;
      })
      ...
      /* HERE */
      ...

}

getPrimaryInfo(): Observable<any> {}
getPermissions(): Observable<any> {}
...

At the /* HERE */ point, depending on this.status value (Authenticated specifically) I would like to fire two more HTTP requests (via getPrimaryInfo and getPermissions methods) in order to get some user's details from the backend. After both complete, I would like to return this.status as returned value of signInBasic method. If the user is not authenticated, I will anyway return this.status with AuthenticationStatus.NotAuthenticated value since it was set before.

I was looking to forkJoin but I don't understand how I can return something only when those two HTTP calls complete.

2

2 Answers

2
votes

You can use concatMap to wait for forkJoin to complete and then map the result into this.status regardless of what the two requests returned.

signInBasic(user: string, pwd: string) {
  return this.http.post('some_url', params, ...)
    .concatMap((response: HttpResponse<Object>) => {
      this.status = response.status === 200 ? AuthenticationStatus.Authenticated : AuthenticationStatus.NotAuthenticated;

      if (this.status === AuthenticationStatus.Authenticated) {
        return forkJoin(getPrimaryInfo(), getPermissions())
          .pipe(
            map(() => this.status),
          );
      } else {
        return of(this.status);
      }
    });
}
0
votes

switchMap with a projection function is your friend in this case:

return this.http.post('some_url', params, { observe: 'response', responseType: 'text' })
  .map((response: HttpResponse<Object>) => {
    this.status = response.status === 200 ? AuthenticationStatus.Authenticated : AuthenticationStatus.NotAuthenticated;
    return this.status;
  })
  .switchMap(status => (status === AutheticationStatuses.Authenticated)
                          ? forkJoin(getPrimaryInfo(), getPermissions())
                          : of(null),
             (status, inner) => status);