ashfaq.p
ashfaq.p

Reputation: 5469

Make synchronus http requests with Observables

I am working on angular 2 project. I have to make n number of http Requests. But i need to wait to get the data from previous request to make next request.

How can I achieve this with Observables.

I am doing:

_.forEach(data, (path) => {
        this.userService.getTreeNodes(path.id)
          .subscribe(
            data => {
              //do something
            }
          );
      });

So right now, three simulatneous requests are going.

Upvotes: 2

Views: 146

Answers (2)

sjiffa
sjiffa

Reputation: 113

Here is an example for a login function that first gets a accessToken from facebook, then sends that token to a second service to get the user profile.

login(): Observable<any> {

let fas: FacebookAuthResponse = {
  accessToken: null,
  expiresIn: null,
  signedRequest: null,
  userID: null,
};

let fbResponse: Subject<any> = new Subject();
let userProfile: Subject<any> = new Subject();

this.fb.login().then((response: FacebookLoginResponse) => {
    fbResponse.next(response.authResponse);
  }), (error: any) => {
  console.error(error);
};

fbResponse
  .map((far: FacebookAuthResponse) => far.accessToken)
  .mergeMap(accessToken => this.processLogin(accessToken))
  .subscribe(res => userProfile.next(res));

return userProfile

}

processLogin(token){

let headers = new Headers({ 'Authorization': 'Bearer facebook ' + token });
let options = new RequestOptions({ headers: headers });

return this.http.get('http://localhost:8000/user-profile/', options)

}

Here I use rxjs Observable and rxjs Subject. I would recommend reading this article: http://blog.angular-university.io/how-to-build-angular2-apps-using-rxjs-observable-data-services-pitfalls-to-avoid/

fbResponse.next(response.authResponse);

When this.fb.login is resolved, call next on the fbResponse Subject to further process the fb.login response.

.map((far: FacebookAuthResponse) => far.accessToken)

here map is used to get the accessToken from the fbLogin response.

What happens next is not part of your question, but might be interesting.

.mergeMap(accessToken => this.processLogin(accessToken))
.subscribe(res => userProfile.next(res));

mergeMap let's us subsribe to the last call in the request chain, and return that value.

So when we subscribe to this login request, the user profile from the last call is returned when all request are completed synchronously.

Upvotes: 1

Emre &#214;zt&#252;rk
Emre &#214;zt&#252;rk

Reputation: 2860

flatMap - Operator is the keyword, which will help you to solve your problem.

flatMap is how we handle dependencies between observables. My sample is contrived, but I am returning a value from the first observable that is needed by the second observable to calculate a sum.

Like I said this example is contrived, but if we compare this to promises, flatMap is how we would create the equivalent of promise chains. The code can be seen below.

let first = Observable.of(10);
first.flatMap((operand1) => {
  return Observable.of(operand1 + 10);
})
.subscribe(res => this.flatMappedStreams = {msg: '10 + 10 = ' + res});

Source from http://www.syntaxsuccess.com/viewarticle/combining-multiple-rxjs-streams-in-angular-2.0

Upvotes: 1

Related Questions