1

Core Question:

I'd like to get the following response into a string rather than an observable.

getFacebookPhoto(uid: string): Observable<any> {
    let results = this.http.get('https://graph.facebook.com/' + uid + '/picture?height=200&redirect=false')
    .map(response => response.json().data.url.)
    return results
}

Additional Information:

I need to populate a list of available photos for my users to choose from. I'm binding the url's of those photos to the template with interpolation with something like {{ selectedPic }}. Ideally, something like, (click)="selectedPic = gravatarUrl" would change the value of selectedPic to the value of gravatarUrl, or any of the variables in my component that have string values of a url.

The issue is that facebookPhoto is an observable. I'd like to store the emission as a string.

Update:

This achieved the goal of storing the emission in the string type variable selectedPic:

this.memberCreationService.getFacebookPicUrl(uid)
.subscribe(picUrl => this.selectedPic = picUrl)

Is there a way to do this without creating a subscription, however? Something that gets the emission and disposes of the observable maybe...

J. Adam Connor
  • 1,694
  • 3
  • 18
  • 35

2 Answers2

1

No, you're subscribing to the event, and the data literally isn't present until it reaches the application.

The Http module is making an async web request to fetch data, so you need to subscribe to be informed when the data is present (and take some action, such as assign the data to a variable.

The subscription is necessary.

chrispy
  • 3,552
  • 1
  • 11
  • 19
1

In angular2's Http from '@angular/http'. http.get will always return an Observable object, you can see it in the function's signature:

get(url: string, options?: RequestOptionsArgs): Observable<Response>;

This is because this function runs asynchronously, if when you want to fetch data from a server it will have to wait, so it can't just return the string/json object you requested right away.

You should subscribe to the observable after the function call by using the .subscribe function it returns, or use .toPromise() if you imported the 'rxjs/operator/add/toPromise' module

ex:

getFacebookPhoto("abcd123").subscribe(response => {
    this.myObject = response.json();
}

I'd suggest you read about Observables or Promises here.

Also, you don't need to use {{}} in here: (click)="{{selectedPic = gravatarUrl}}"

Community
  • 1
  • 1
Omri Luzon
  • 3,975
  • 6
  • 20
  • 29
  • Thanks for the responses, guys. I do understand that I have to subscribe to the observable. What I'm asking, is what is the best way to operate on the observable to get the targeted emission into a string. Also, the curly brackets in the template statement was a mistake. – J. Adam Connor Feb 16 '17 at 20:08
  • That's why I included a second code block that you can see how to use the function you defined. – Omri Luzon Feb 16 '17 at 20:12
  • Your function signature was `getFacebookPhoto(uid: string): Observable` To use it you can subscribe to it where you need and pass the response.json() to it. – Omri Luzon Feb 16 '17 at 20:15
  • Oh, ok. I did something similar in my question already. Thanks for your answer. – J. Adam Connor Feb 16 '17 at 20:18
  • 1
    Take a look at this: http://stackoverflow.com/questions/33295207/how-to-synchronise-angular2-http-get – Omri Luzon Feb 16 '17 at 20:19
  • That's actually good to know. I guess I was hoping for a way to have the method in the service return the string. Not a good idea apparently. – J. Adam Connor Feb 16 '17 at 20:22
  • 1
    Just to be a bit more correct, there is an option to achive what you requested, using the ES2017 feature called [async function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) You can scroll down and see that it is not widely supported. – Omri Luzon Feb 17 '17 at 16:54