Reputation: 372
I need to call a service with an async (http) return, and use it's output as an additional input to a service method (which returns an observable). What's the best way to do this in Angular 4+?
I have tried 'chaining' the results in the "subscribe" method of the first service, but doing this my service always returns 'null'.
public secondServiceCall: Observable<object> {
this.firstService.next().subscribe(result=> {
item.number = result;
return this.httpService.post<object>('/new', item);
});
}
I expected that the function wouldn't return until the subscription for the firstService was completed (async like), but this didn't happen - and instead I got 'null' in my calling function.
I have also tried to use the firstService call as an observable - this returns the second observable correctly, but never waits for the "then" function to execute before firing the second observable.
this.firstService.next().toPromise().then(result=> {
item.number = result;
});
return return this.httpService.post<object>('/new', item);
Upvotes: 1
Views: 2667
Reputation: 1103
In your case it's not important which combining operator to use: flatMap
, concatMap
or switchMap
; they will behave the same because Angular
's http
emits a value only once and immediately completes.
Usually you would like to prefer concatMap
more because this operator respects the order of emissions (meaning that if you have some delayed calls in your Observables they will be executed one after another, while flatMap
and switchMap
can lead to uncertain results, more details here https://www.baeldung.com/rxjava-flatmap-switchmap).
TLDR; Use concatMap
this.http.get('one').pipe(
concatMap(result => this.http.get('two'))
)
Upvotes: 5
Reputation: 9880
Import the switchMap operator:
import { switchMap } from 'rxjs/operators';
Whatever the method in firstService
that returns an observable of whatever item
is, wrap that as such:
public secondServiceCall: Observable<object> {
return this.firstService.someMethod().pipe(
switchMap(item => {
return this.httpService.post<object>('/new', item);
})
) // result of your HTTP call based on item from firstService is now available when you subscribe
}
What this does is execute whatever your firstService
method is which returns an Observable<item>
, then switches over to the httpService.post
call, which is supplied the result of the firstService
method as the first argument.
Edit: Thanks JB Nizet, combined multiple iterations of the answer :/
Upvotes: 7