Practice of observables in Angular

First steps working with observables in an application developed with Angular.

In the previous article we offered a . Now we are going to get down to work to see how all this translates into code, through a simple practical example.

In this article we will work with observables, using the RxJS library, which is the one Angular relies on to introduce this development pattern, capable of significantly increasing application performance.

For this practical application we are going to start from an example that we had already been working on previously in this manual. So that no one gets lost, we leave the reference to the example on which we are going to apply the observables: .

In that last article we were able to develop two components, which shared the same data store (an array of client objects). In the registration component, new objects were generated and introduced into the array and in the listing component they were displayed. Our service was in charge of maintaining this data store and serving as a communication bridge between both components. The example worked perfectly and in small applications we don’t need anything else. But if we have a large application, or a medium one where we need to maintain better performance, applying the observables will be a much better option.

What we need to implement observables

If you read carefully the previous article, dedicated to , I think you can more or less have an idea of ​​what we are going to need in this implementation step. In any case, a little review to clarify the ideas never hurts. In summary, these are the actors that we are going to use:

  • A subject: which is in charge of generating and issuing the update events of the data store.
  • An observable: which is an object that allows observing the events emitted by the subject.
  • A subscription: generated from the observable.

Note: Other implementations may bring into play other types of objects, available in the observer pattern and in the RxJS library.

The client service will be in charge of using the “subject” to generate the events when new clients are added. This service will also be in charge of delivering the observable to the components that need to listen to the events emitted by the subject.

Those components listening for events are the observers. These observers declare and use the observable and, through a subscription, will be aware of any changes to what is being observed.

We hope that these concepts are fairly clear, since it will be essential to be able to understand the rest of the exercise. Next we can begin to review in detail the code necessary to carry out all these operations.

Produce the flow of events to observe

The service that implements all the data access part, with the business logic of the application, is in charge of generating the events that the observers will be able to consume.

The service therefore has to know the implementation of two classes:

  • The subject, to generate the event stream
  • The observable, which will be delivered on demand to the observers

To do this, in the client service “clientes.service.ts” we are going to create the corresponding imports:

import { Observable } from ‘rxjs/Observable’; import { Subject } from ‘rxjs/Subject’;

As you can see, these imports are not offered by the Angular library, but by the RxJS library, which was installed as a dependency when creating the Angular application.

Declaration of the subject as a property

The subject will be an element of the service and therefore we have to declare it like any other property. Its declaration is made by the following code.

private customers$ = new Subject();

  • We make the declaration private, so that nobody can access the subject, except the service itself.
  • The name of the private property is customers$. It is normal for subjects in working with observables to have the “$” character at the end, to make it clear what they are.
  • We use a TypeScript “generic” to indicate the type of what we are going to observe. What we are going to observe is the array of clients, that is why in the instantiation of the subject the generic type is defined as Client.
  • It is not necessary to indicate the type of the property series$: Subject because it is perfectly inferred, since the instantiation of the subject is done on the same line of the property declaration.

Emit events using the subject

Now, also in the service, whenever a new element is added to the clients array, we have to emit an event, using the subject. We achieve this, of course, using the RxJS subject object.

This would be the method that adds a client, who already had our service previously. Only before, only the push() was performed and now we continue performing the insertion in the array and later the generation of the event with the subject.

addCustomer(customer: Customer) { this.customers.push(customer); this.customers$.next(this.customers); }

As you can see, the method to create the event is “next” and we also have to pass the state of the array at this moment, so that later the observers can know how the array was when this event occurred.

Generate the observable

The last action that we are going to need to complete the work within the service is the generation of the observer, which will be delivered to all those components that want to observe changes in the data store.

This step is interesting, since the observable is a consumer of the subject’s events and is read-only. That is, he can be attentive to events, but is unable to do anything else. Therefore, the only thing that the service will deliver to externally, to any component that needs it, is this observable. Through the observable, components will know when the datastore has changed, but no component will be able to generate new datastore change events, which is a responsibility of the service and the main task of the private subject.

The observer will be created by a method of the subject called asObservable(). We’ll use a “getter” method to return the observable, which will look like this.

getCustomers$(): Observable { return this.customers$.asObservable(); }

As you can see, the method returns an object of the Observable class, which must also be defined by specifying, through a TypeScript generic, what that observable is capable of monitoring, in this case an array of clients (Customers).

consume an observable

Now, in any component that we need to listen for changes in the data store, we can use the observable provided by the service. For this we only need a couple of steps.

The first is to import the Observable class.

import { Observable } from ‘rxjs/Observable’;

Next, we are going to create a property in the component that allows us to store the observable. We can see that the type is declared, but not initialized yet.

customers$: Observable;

Note: Again, to guide whoever is reading this code, we put a $ at the end of the variable name, indicating that it is an observable.

Create event subscription

The second is to create the subscription to the events that the observable gives us, and that were generated in the service using the subject.

The appropriate place to generate this subscription is the ngOnInit() method, which is executed when the component has already been initialized and therefore has all its properties already available. It will have this form:

ngOnInit() { this.customers$ = this.customersService.getCustomers$(); this.customers$.subscribe(customers => this.customers = customers); }

Note: We will do this in any other component that needs to use the observable. Obviously, in the constructor of the ListadoClientesComponent component, the service that is needed to request the observable must have been injected.

In the above code we do two steps:

  • The observable is accessed through the getClientes$() method of the clientesService service. That observable is the one that can listen to the events that we need to consume.
  • A subscription is created using the subscribe() method of the observable. This subscription method must receive the event handler function that contains the code to execute when the event is fired. The event handler function receives the array being watched as a parameter.

Note: You can see that we are using an “arrow function” for the subscription event handler definition. We could have just as well used an anonymous function as you may be used to, but an “arrow function” is preferable here for two reasons. 1) The syntax is more concise and reduced. But more importantly 2) the arrow function does not generate its own context, so we can still access “this”. If you wish, you can obtain much more information about the .

Basically, what the subscription event handler does is, every time the customer array changes, it updates the internal property of the component to the new updated array, received by parameter.

In this way, the list of clients can receive the new array of clients, each time it is updated, in an optimized way, since it does not have to ask all the time if that array has been updated, just sit and wait and be notified. every time there are changes.

After making these modifications, your application should continue to work as before, showing clients in the list each time the client registration component generates a new one.

To resolve possible doubts regarding the complete code of the project, as we have left it in this step, I leave you this link to a commit in a repository of the example on GitHub.

In the next installment, we are going to explain another fundamental thing in this process, which you must learn to complete the flow: unsubscribe from observables.

See also  Event types in Javascript
Loading Facebook Comments ...
Loading Disqus Comments ...