ReactiveX observable that uses another observable I am trying to write an Angular service that will wrap the regular Http service and automatically make authentication calls if Bearer token is not available or invalid.

Here's an illustration of a regular GET call made via the service:

this.httpWithAutomagicAuth
    .get("http://localhost:5001/books")
    .map(res =&gt; res.json())
    .subscribe(
        data =&gt; {
            self.data = data;
        }
    );


And here's my very sloppy implementation for such service. Obviously, I'm not using the right ReactiveX idioms in the code.

As you can easily notice I am trying to build an observable (Observable.create) that is using another observable returned by this.login(). I am sure there is a better way of chaining/nesting observable for this scenario.

Please, suggest improvements that will make code:


terse
easy to read and understand

@Injectable()
export class HttpWebApiAuthService {

constructor(private http: Http) { }

// ...

public get(url: string, options?: RequestOptionsArgs): Observable&lt;Response&gt; {
    // TODO this code is for test purpose only (basically, it required to enforce the jwtToken retrieval branch execution)
    // this.clearJwtToken();

    if (!this.getJwtToken()) {
        return Observable.create(
            (result: Observer&lt;Response&gt;) =&gt; {
                this.login()
                    .map(res =&gt; res.json())
                    .subscribe(
                        data =&gt; {
                            this.saveJwtToken(data.id_token);

                            this.executeGet(url, options)
                                .subscribe(authenticationResult =&gt; {
                                    result.next(authenticationResult);
                                });
                        },
                        error =&gt; { console.error("Authentication error", error); },
                        () =&gt; { console.info("Authentication complete"); }
                    );
                },
                error =&gt; { console.error("OBSERVABLE error: ", error); },
                () =&gt; { console.info("OBSERVABLE complete");
            }
        );
    } else {
        return this.executeGet(url, options);
    }
}

private login() : Observable&lt;Response&gt; {
    const authBody =
        {
            "client_id": "...",
            "username": "...",
            "password": "...",
            // ...
        };
    const headers = new Headers();
    headers.append("Content-Type", "application/json");

    return this.http.post("https://AUTH_URL", JSON.stringify(authBody), { headers: headers });
}

// ...

}
I had to use flatMap to achieve what I wanted:

public get(url: string): Observable&lt;Response&gt; {
  return this
    .login()
    .flatMap(token_id =&gt; this._http.get(url));  // token_id can be used here
}

public login(): Observable&lt;string&gt; {
  const authBody =
      {
          "client_id": "...",
          "username": "...",
          "password": "...",
          // ...
      };
  const headers = new Headers();
  headers.append("Content-Type", "application/json");

  return this._http
    .post('AUTH_URL', authBody)
    .map(response =&gt; response.json().token_id);
}