Reputation: 95
I am trying to do a basic chaining of RxJS HTTP calls where the first call is going to pass the ID of an object that was created server-side into the second call. What I am observing with my implementation is that only the first call is made and the second chained call is never executed.
Below is roughly the code that I have.
First call:
createItem(itemData) {
return this.http.post(createUrl, itemData)
.map((res) => res.json())
.catch(this.handleError);
}
Second call:
addFileToItem(id, file): Observable<any> {
return this.http.post(secondUrl + id, file)
.map((res) => log(res))
.catch(this.handleError);
}
Function defined mapping one call into the other:
createAndUpload(itemData, file): Observable<any> {
return createItem(itemData, file)
.map((res) => {
if (file) {
return addFileToItem(res.id, file);
}
});
}
And finally, where the observable is executed through a subscribe()
:
someFunction(itemData, file) {
createAndUpload(itemData, file)
.subscribe(res => {
log(res);
//go do something else
};
}
Upvotes: 3
Views: 2661
Reputation: 96891
The problem is in createAndUpload
where map
just turns the result from the first call into an Observable but you never subscribe to it.
So simply said you just need to use mergeMap
(or concatMap
in this case it doesn't matter) instead of map
. The mergeMap
operator will subscribe to the inner Observable and emit its result:
createAndUpload(itemData, file): Observable<any> {
return createItem(itemData, file)
.mergeMap((res) => {
if (file) {
return addFileToItem(res.id, file);
}
return Observable.empty(); // you can't return `undefined` from the inner Observable
});
}
Upvotes: 3
Reputation: 95
Apparently the map()
function doesn't actually return anything, meaning that an Observable
object is not returned. Instead, a transforming operator such as mergeMap
is needed.
Here is the code that ended up working, also using the "newer" .pipe()
operator. The only place the code needed to be changed was in the Observable function where I defined the combination of the two separate Observables. In order to access the mergeMap
operator, don't forget to import it from rxjs/operators
.
For a reason that I will eventually figure out, I couldn't access the mergeMap
without the pipe...
createAndUpload(itemData, file): Observable<any> {
return createItem(itemData, file)
.pipe(
mergeMap((res) => {
if (file) {
return addFileToItem(res.id, file);
}
})
)
}
Upvotes: 1