How do I resolve an Observable inside of another Observable? - rxjs
Solution 1
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));
Solution 2
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
};
});
Related videos on Youtube
Comments
-
jhamm over 1 year
I have an
Observable
in which I consume another observable, but the 2ndObservable
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 anObservable
, but it is never resolved. I have tried to add aflatMap
and aconcat
, but it still isn't resolved. How do I get thegetMe
to resolve? -
user3743222 over 8 yearsPOJO = Plain Old Javascript Object
-
jhamm over 8 yearsThank you for the help, but this seems more convoluted than using
Promises
. There has to be a more concise way. -
user3743222 over 8 yearsSure let's see what others come up with. Question : why don't you use promises, and then convert to observable when you have the result you want?
Rx.Observable.fromPromise
does that, that way you have the best of both worlds. -
user3743222 over 8 yearsInteresting proposition. Could be valuable to test it. In my opinion a possible problem is accessing
res
from the closure. I am not sure about this, but the anonymous function withres.me
in its body, is executed/evaluated only whengetMe
emits a value, at which time I wonder if theres
variable still holds its value. I code defensively around this by using only pure functions in connection with observables. So I am interested to know if I am being too cautious. -
Jeremy over 8 yearsFrom a closure perspective,
res
will still hold it's value (I have used this technique before). I do concur that it's best to having a defensive style of coding and to test thoroughly. As a side note, if there's a secondRx.Observable.fromPromise(axios(config))
execution beforegetMe()
resolves then you'll have 2 subscribe executions. This can easily be remedied by usingflatMapLatest
which will ensure that you'll always get the latestgetMe()
response with one subscribe execution. -
user3743222 over 8 yearsfair enough. Thanks for the clarification.
-
paulpdaniels over 8 yearsBe careful in your description of
fromPromise
as a cold Observable. Though the value itself will be cached, making it appear as a cold Observable to all down stream subscribers. Thepromise
itself is eager and will begin execution immediately, regardless of subscription. -
mahatmanich about 7 yearsPOJO has been taken loooong looong ago by JAVA => Plain Old Java Object. Javascript was not OOP back then ....