After @Pac0 has provided a comprehensive overview of the various solutions, I would like to offer a slightly different perspective.
Blending Promises and Observables
Personally, I lean towards avoiding mixing Promises and Observables when using async/await with Observables. Despite their superficial similarities, they are fundamentally distinct.
- Promises are inherently asynchronous, while Observables may not be
- Promises convey a single value, whereas Observables can emit 0, 1, or many values
- Promises are limited in functionality, lacking features like cancellation, unlike Observables which are more versatile (e.g., managing multiple WebSocket connections)
- They have different APIs
Utilizing Promises in Angular
Although there are scenarios where utilizing both is acceptable, particularly with Angular, it's advantageous to delve deeper into RxJS. This is due to:
- Angular's API heavily relies on Observables (e.g., router, http...), aligning with RxJS enhances interoperability and capitalizes on RxJS's capabilities without the need for frequent Promise conversions
- Angular's
async
pipe facilitates composing a seamless data flow within your application, allowing for streamlined manipulation of data from services to templates without interruption or manual handling
However, there are instances where using Promises can still be beneficial. For example, the clarity provided by Promises over Observables in specifying the type of data to be expected (single value, multiple values, or completion).
It's essential to strike a balance between Promises and Observables in your project. Promises are ideal for expressing completion status or sequential code execution with async/await
, simplifying code. On the other hand, if advanced data management is required, Observables are more suitable.
Regarding Your Example
My suggestion is to embrace the capabilities of RxJS and Angular together. In your example, you can implement the code as follows:
this.result$ = Observable.forkJoin(
this.serviceA.get(),
this.serviceB.get(),
this.serviceC.get()
);
this.result$.subscribe(([resA, resB, resC]) => ...)
By using forkJoin
, you can handle multiple requests concurrently and receive the combined results efficiently. Alternatively, utilizing Observable.zip
would yield similar results with a slight variation in behavior.
Edit: To address the need for the results of previous HTTP requests, consider implementing the flatMap
approach outlined in @Pac0's answer.