Call Promise Method inside Observable Method


#1

Hello I am having trouble with some code.
So I have this method returning an Observable. I use it to search tracks using the spotify API.
But the thing is that I need an Authorization Oauth2 token to use the Spotify API.
So I am trying to create a method that will handle the token. I want it to check if the token is still valid and get a new one if it is not. It will then return the token. So this last method returns a Promise.
Now when I try to implement the call of the getToken() method inside my first method, it doesn’t work.
Here is the method:

  search(query: string): Observable<SpotifySearchResult[]> {
    let params: string = [
      `q=${query}`,
      `type=track`
    ].join('&');
    let queryUrl: string = `${this.apiBase}search?${params}`;

    return this.tokenService.getToken().then(token => {
      return this.http.get(queryUrl)
        .map((response: Response) => {
          return (<any>response.json()).track.items.map(item => {
            var artists: Array<string>;
            for (var i = 0; i < item.artists.length; i++) {
              artists.push(item.artists[i].name);
            }
            var album = new Album({
              id: item.album.id,
              name: item.album.name,
              image: item.album.images[0].url
            })
            return new SpotifySearchResult({
              id: item.id,
              name: item.name,
              type: item.type,
              uri: item.uri,
              artists: artists,
              album: album
            });
          });
        });
    })
    
  }

Maybe this is not the right way to do so and maybe I just miss some knowledge that will unstuck me.
Please help if you can.

Thanks


#2

Can you write a flowchart in English of what you want to make happen?


#3

You can convert the promise into an observable using fromPromise and then use flatMap to chain them together, e.g.

search(query: string): Observable<SpotifySearchResult[]> {
  let params: string = [
    `q=${query}`,
    `type=track`
  ].join('&');
  let queryUrl: string = `${this.apiBase}search?${params}`;

  return fromPromise(this.tokenService.getToken())
  .flatMap(token => this.http.get(queryUrl))
  .map((response: Response) => {
    return (<any>response.json()).track.items.map(item => {
      var artists: Array<string>;
      for (var i = 0; i < item.artists.length; i++) {
        artists.push(item.artists[i].name);
      }
      var album = new Album({
        id: item.album.id,
        name: item.album.name,
        image: item.album.images[0].url
      })
      return new SpotifySearchResult({
        id: item.id,
        name: item.name,
        type: item.type,
        uri: item.uri,
        artists: artists,
        album: album
      });
    });
  });
}

#4

Thank you so much @SigmundFroyd thanks to your fromPromise().flatMap method I was able to make it work like I wanted. This helped me out so much. =)