Reputation: 25032
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?
Upvotes: 14
Views: 24243
Reputation: 194
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));
Upvotes: 12
Reputation: 18663
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
};
});
Upvotes: 2
Reputation: 18665
Sample code to find below (UNTESTED!!). Some explanations :
getMe
is not flattened ('resolve' belong to the world of promises) because the map
operator does not flatten observables. flatMap
do, but you need to use it in the form source.flatMap(function(x){return observable})
and here what you return is a POJO
not a Rx.Observable
.getMe
we use a flatMap
.accessToken
and refreshToken
) we use withLatestFrom
on the observable who emitted the res
object (res$
).We use share
as we subscribe twice to res$
, and we want all subscribers to see the same values.
var res$ = Observable
.fromPromise(axios(config))
.map(function ( res ) {
return {
accessToken : res.data.access_token,
refreshToken : res.data.refresh_token
}
})
.share();
var getMe$ = res$.flatMap(function ( res ) {return getMe(res.accessToken)});
var finalRes$ = getMe$.withLatestFrom(res$, function ( getMe, res ) {
return {
me : getMe,
accessToken : res.accessToken,
refreshToken : res.refreshToken
}
});
function getMe ( accessToken ) {
return Observable.fromPromise(axios.get({url : 'https://api.spotify.com/v1/me'}));
}
Upvotes: 0