RxJS in Angular – Single Result Data Streams and Async Pipe

In the first and second part of this small series, we have discussed implementations that have flaws and can introduce side-effects to our data flow. We have learned how combining our streams and modeling our our data flow to yield a single result helped with solving the introduced problems.

In diesem Artikel:

yb
Yannick Baron ist Architekturberater bei Thinktecture mit einem Fokus auf Angular und RxJS.

In this third part of the series we want to talk about another advantage when modeling our streams in this manner, specifically in the context of an Angular application.

Composing Data Streams to Yield a Single Result and Leveraging the Async Pipe

Similar to the previous posts, we want to combine streams to retrieve from multiple entities. This time however, we make sure that the final product of our stream is our view model.

For this example we keep it rather simple and combine the request for a user object with the request for a list of roles in our system, so we can fill the view with a nicer representation than just a role id.

				
					// Stream that emits an user object when the userId route param changes
const user$ = this.route.params.pipe(
  switchMap(({ userId }) => requestUser(userId)),
);

// Stream that emits a list of all role objects once
const roles$ = requestRoles();

// Combine both streams
const userAndRoles$ = combineLatest(user$, roles$);

// Transform combined result into UserView model
this.userView$ = userAndRoles$.pipe(
  // Create a UserView object containing the user's properties and its roles
  map(([user, roles]) => ({
    ...user,
    roles: resolveUserRoles(user, roles)
  }))
);
				
			

In the implementation above, we create two streams. One to request and emit a new user object when the userId route param changes, and one to emit a list of all roles once (technically, we could emit live updates of roles, too). We use the combineLatest operator which combines the latest emit of the given streams into a single emit. In our case this serves two purposes. First, once the user$ emits again, which happens when we change the route accordingly, the same pipeline runs and the view will be updated with the new user and its respective roles. Additionally, we cannot display the view until the roles are received. combineLatest will hold back on its emit, until both streams have produced a value.

Finally, we can now use the userView$ stream in our template and subscribe to it via the async pipe. This way we do not even have to handle subscriptions. Another advantage of using the async pipe is that we can easily switch our change detection strategy to OnPush as the template will only need to be updated when our stream emits.

				
					<dl *ngIf="userView$ | async as userView">
  ...
</dl>
				
			

You can see this live on stackblitz.

https://stackblitz.com/edit/angular-ci9trw?file=src/app/app.component.ts

Conclusion

In this series so far, we briefly discussed how combining our streams to yield a single result helps us eradicate potential side-effects. We now illustrated how following this principle can make working with streams in Angular applications easier, as the async pipe implicitly handles subscriptions for us. Ultimately, this comes with performance improvements, as we can make use of the OnPush change detection strategy.

Kostenloser
Newsletter

Aktuelle Artikel, Screencasts, Webinare und Interviews unserer Experten für Sie

Verpassen Sie keine Inhalte zu Angular, .NET Core, Blazor, Azure und Kubernetes und melden Sie sich zu unserem kostenlosen monatlichen Dev-Newsletter an.

Newsletter Anmeldung
Diese Artikel könnten Sie interessieren
Low-angle photography of metal structure
AI
cl-neu

AI-Funktionen zu Angular-Apps hinzufügen: lokal und offlinefähig

Künstliche Intelligenz (KI) ist spätestens seit der Veröffentlichung von ChatGPT in aller Munde. Wit WebLLM können Sie einen KI-Chatbot in Ihre eigenen Angular-Anwendungen integrieren. Wie das funktioniert und welche Vor- und Nachteile WebLLM hat, lesen Sie hier.
26.02.2024
Angular
SL-rund

Konfiguration von Lazy Loaded Angular Modulen

Die Konfigurierbarkeit unserer Angular-Module ist für den Aufbau einer wiederverwendbaren Architektur unerlässlich. Aber in der jüngsten Vergangenheit hat uns Angular seine neue modullose Zukunft präsentiert. Wie sieht das Ganze jetzt aus? Wie konfigurieren wir jetzt unsere Lazy-Komponenten? Lasst uns gemeinsam einen Blick darauf werfen.
03.08.2023
Angular
yb

Using EntityAdapter with ComponentStore: @ngrx/entity Series – Part 3

As someone who enjoys the ComponentStore on an average level, I have written simple reactive CRUD logic several times. While storing a vast number of entities in the component state might not be a frequent use case, I will briefly illustrate the usage of the EntityAdapter with the @ngrx/component-store.
14.02.2023
Angular
yb

Multiple Entity Collections in the Same Feature State: @ngrx/entity-Series – Part 2

After introducing the @ngrx/entity package, I am often asked how to manage multiple entity types in the same feature state. While I hope that the previous part of this article series has made this more apparent, I will further focus on this question in the following.
07.02.2023
Angular
yb

Managing Your Collections With the EntityAdapter: @ngrx/entity-Series – Part 1

This three-part series of blogposts is targeted at developers who have already gained experience with NgRx but still manage their collections themselves. In the first part I introduce the Entity Adapter, in the second part I show you how to connect it to NgRx and in the third part how to do it with the Component Store as well.
31.01.2023
Angular
MS-rund

Implementing Smart and Presentational Components with Angular: Condensed Angular Experiences – Part 4

In this article, we will explore how to apply the concept of smart and presentational components with Angular. We will choose a complex-enough target to see all aspects in action, yet understandable and within the scope of this article. The goal is to teach you how to use this architecture in your way. For that, we will iterate through different development stages, starting with the target selection and implementing it in a naive way. After the first development, we will refactor that naive solution into smart and presentational components that are reusable, refactor-friendly, and testable.
23.01.2023