4

What is "best practices" for chaining a sequence of HttpClient calls (assume the current call depends on the results of the previous calls)? The following solution is functional but apparently not recommended. Each get returns an Observable. Use of the "pipe" operator preferred in solution (the newer approach in RxJs).

ngOnInit() {
  this.firstService.get().subscribe((first) => {
    this.secondService.get().subscribe(second => {
      this.thirdService.get().subscribe(third => {
        ... possibly more nested calls ...
      })
    })
  })
}
1

2 Answers 2

14

Your code is far beyond best practice. Never do subscription inside another.

If your tasks are three seperate tasks/observables which do not depends each other, then consider to use forkJoin (all Observables start at the same time and when the last observable finishes It returns result)

let observable1(param1);
let observable2(param2);
let observable3(param3);

let joinedObservables = forkJoin(observable1, observable2, observable3).subscribe(x => {
  let result1 = x[0];
  let result2 = x[1];
  let result3 = x[2];

  ...
});

If their results depends on each other you can use switchMap, flatMap, mergeMap, exhaustMap (check differences)

let resultObservable =  return this.observable1().pipe(mergeMap((param1) => {
  return this.observable2().pipe(map((param1) => {

    ....        

    return <result>;
  }));
}));

resultObservable.subscribe(x => {
   ...
});
Sign up to request clarification or add additional context in comments.

3 Comments

Yep. I assumed that was a bad practice, but wanted to present that as a typically naive conversion of legacy code based on promises or chained callbacks, that makes the contrast with a proper solution clear.
If you believe that this answer is helpful please consider to mark it as amswer so that the community can benefit from it
Bumped it. Thanks.
3

If the reason why you need nested calls is to use data from the previous calls, I recommend using the pipe operator with mergeMaps and more pipes/maps to return the next calls in place of the previous.

Should be something similar to (subscribes and unsubscribes omitted):

this.firstService.pipe(
    mergeMap(res =>
        this.secondService.get().pipe(
            map(data => data),
        ),
    ... <more as needed>
);

If they don't need to be nested, it's easier to do this.service.get().toPromise() inside a promiseAll.

2 Comments

I don't see any advantage in using Promises which are a legacy version of Observable (that emit once) and even when making a HTTP call (completes after receive) there are benefits to using an Observable and associated operators.
What makes a promise the legacy version of an observable? async/await styles of programming with promises are both very new and widely used. Angular uses both frequently for different purposes. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… shows their utility expanding even more so recently. It's just another opinion and another style of tools to use to do a similar job. The point here is one-shot (promise) vs stream (observable).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.