Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I resolve an Observable inside of another Observable? - rxjs

I have an Observable in which I consume another observable, but the 2nd Observable I can't get to resolve. Here is the code:

return Observable.fromPromise(axios(config))
        .map(res => {
            return {
                accessToken: res.data.access_token,
                refreshToken: res.data.refresh_token                
            }
        })
        .map(res => {
            return {
                me: getMe(res.accessToken),
                accessToken: res.accessToken,
                refreshToken: res.refreshToken                
            }
        })

function getMe(accessToken) {
    return Observable.fromPromise(axios.get({
        url: 'https://api.spotify.com/v1/me',
    }));
}

The getMe function returns an Observable, but it is never resolved. I have tried to add a flatMap and a concat, but it still isn't resolved. How do I get the getMe to resolve?

like image 937
jhamm Avatar asked Dec 09 '15 23:12

jhamm


People also ask

How do you call one Observable after another?

Make a single observable out of the several ones that need to be executed in parallel (i.e. the many deletions), using forkJoin. Use switchMap to execute one observable after another.

What is FlatMap in RXJS?

The FlatMap operator transforms an Observable by applying a function that you specify to each item emitted by the source Observable, where that function returns an Observable that itself emits items. FlatMap then merges the emissions of these resulting Observables, emitting these merged results as its own sequence.

What happens when you subscribe to an Observable?

Observables are declarative —that is, you define a function for publishing values, but it is not executed until a consumer subscribes to it. The subscribed consumer then receives notifications until the function completes, or until they unsubscribe.

Does MAP return an Observable?

The map() operator's return value is observable that emits the values from the source Observable transformed by the given project function.


2 Answers

Did you try the following (Also untested):

function getMe(accessToken) {
  return Rx.Observable.fromPromise(axios.get({
    url: 'https://api.spotify.com/v1/me',
  }));
}    

Rx.Observable.fromPromise(axios(config))
    .map((res) => {
        return {
            accessToken: res.data.access_token,
            refreshToken: res.data.refresh_token                
        }
    })
    .flatMap((res) => {
        return getMe(res.accessToken).map((res2) => {
          res.me = res2;
          return res;
        }
    })
    .subscribe((data) => console.log(data));

As mentioned in the above post, flatMap returns an observable. map is subsequently used to merge res with the result res2 returned from the second promise.

Also note that fromPromise is a cold observable. This means that you must have a subscription to initiate things. In your case, I presume you already have something like this:

someFunction = () => {
  return Rx.Observable.fromPromise(axios(config))
     ...
     ...
}

someFunction.subscribe((data) => console.log(data));
like image 72
Jeremy Avatar answered Sep 18 '22 23:09

Jeremy


As @user3743222 pointed out, an Observable does not resolve in the sense that a Promise does. If you want the value you of the getMe method you will need to subscribe to the Observable returned by it.

return Observable.fromPromise(axios(config))
        .map(res => {
            return {
                accessToken: res.data.access_token,
                refreshToken: res.data.refresh_token                
            }
        })
        .flatMap(function(tokens) {

          //FlatMap can implicitly accept a Promise return, so I showed that here
          //for brevity
          return axios.get({url : 'https://api.spotify.com/v1/me'});
        },

        //The second method gives you both the item passed into the first function
        //paired with every item emitted from the returned Observable`
        //i.e. axios.get(...)
        function(tokens, response) {
          return {
            accessToken: tokens.accessToken,
            refreshToken: tokens.accessToken,
            //Here response is a value not an Observable
            me: response
          };
        });
like image 28
paulpdaniels Avatar answered Sep 21 '22 23:09

paulpdaniels