Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning an Observable inside a resolved promise

Trying to return an Observable. How should I go about this?

  get(url) : Observable<any> {
    let headers = new Headers();
    this.SetAuthorizationHeader(headers).then(() => { // Resolving a promise
      return this.http.get(url, { // <-- I need to return the Observable from here
          headers: headers
      });
    });
  }

Consumed (not working):

public GetInfo() : Observable<any> {
    return this.authHttpClient.get(this.constants.api_base + "/users/info")
        .map((res: Response) => res.json());
}

Thanks!

like image 351
user1027620 Avatar asked Mar 11 '23 09:03

user1027620


2 Answers

You just need to return this.SetAuthorizationHeader(headers) method, so on resolve of SetAuthorizationHeader method, it will return http.get call observable.

Here you need to remove Observable<any> from get method return type, as actually it is going to return Promise object.

Code

get(url) : any {
    let headers = new Headers();
    //return promise here to continue chain & return inner observable.
    return this.SetAuthorizationHeader(headers).then(() => { // Resolving a promise
      return this.http.get(url, { // <-- I need to return the Observable from here
          headers: headers
      });
    }).map(data => data.json());
}

Consumption

public GetInfo() : any { //here also it will be any, because you are returning `authHttpClient.get` at the end
    return this.authHttpClient.get(this.constants.api_base + "/users/info"));
}

Get Info Consumption

this.user.GetInfo().then(obs => 
    obs.subscribe(
      user => { alert(JSON.stringify(user)); }, 
     (error) => { alert(JSON.stringify(error)); }
);
like image 171
Pankaj Parkar Avatar answered Mar 19 '23 13:03

Pankaj Parkar


Pankaj Parker's works but the return type is Promise<Observable<any>>. That's why the extra .then((obs) => obs.subscribe(...)) is needed.

You can avoid that by transforming your promise to an observable and use concatMap to combine the two.

With concatMap you can control the order of the observables, so the observable that sets the authorization header is emitted before the http request.

Code

  get(url): any {
    let headers = new Headers();
    //transform promise to observable
    const authHeaderObservable = Observable.from(this.SetAuthorizationHeader(headers));

    return authHeaderObservable.concatMap(() => { //return the outer observable
      return this.http.get(url, { // <-- I need to return the inner Observable from here
        headers: headers
      }).map(data => data.json());
    })
  }

Consumption

public GetInfo() : any { //here also it will be any, because you are returning `authHttpClient.get` at the end
    return this.authHttpClient.get(this.constants.api_base + "/users/info"));
}

Get Info Consumption

this.user.GetInfo().subscribe(
      user => { alert(JSON.stringify(user)); }, 
     (error) => { alert(JSON.stringify(error)); }
);
like image 31
Loke Avatar answered Mar 19 '23 14:03

Loke