Two years ago, when I started coding in Angular, I thought observables were some form of weird promises to handle asynchronous calls. It was after Ben Lesh’s talk at the Angular Connection 2016 that I realized its potential. The fact of treating the data as a sequence gave me other ways of coding my solutions, made them more flexible and sustainable. Nowadays, reactive programming is common in my code and rxjs is a key part of my applications. This is the first article in a serie in which I will explain some examples of the problems I faced in my developments with angular and how I applied rxjs to solve them.

Let’s start by improving the performance of ours apps using the change detection strategy “on push”.

Understanding the problem:

In the last weeks some articles have appeared in Medium explaining which is the strategy to change detection “on push”. It seems that it is fashionable. However, I am still finding people who do not understand how Angular change detection works and what exactly “on push” means. Here is my explanation:

Let’s take a look at the next example of Angular in StackBlitz:

As you can see there are three components which are quite similar. All of them have an input which is printed in the component and a counter which increments in one each time the component is rendered. It is a simple but easy way to measure the performance of our components. The component which is rendered less times is the one which consumes less resources. The value of the components input is associated at the text field which each component has over itself. We can change the input of the componentes changing the value of the input text (at least in two of them).

Now we will focus on the first component. This component has the change detection configured in mode “on push”, which means that it is rendered each time the input value changes. In other words, the onChange event in the component’s life cycle is pending changes in the value that is entered into the component. Each time the value changes, the onChange event is reported and the component template is refreshed to update the values that are displayed.

You can see in the example of StackBlitz that the render counter increments one each time you type in the input field.

So, maybe, the question that we have now is why this is not happening in the second component. The answer is easy; because the input value of the component is not changed… even if you type other value in the input text. Let me explain this: In this example the input of the component is an object; which means that it is a memory reference that points at the real value. When we modify the text in the input we are changing the referenced value but not the value of the input which is still being the same memory reference. So the onChange hook does not see any change and it does not render the component to update the view. It is the reason the counter is not incremented… because the view is never refreshed.

The fastest solution to this problem is to change the default change detection strategy … which is the third example, but it has the big drawback of performance. Just take a look at the rendering counter and you will see how it looks like it never stops increasing.What happens here is the following:

OnChange can not detect the changes that occur in the memory references, but we are sure that, if a change occurs, it will happen after a user interaction … and now is when “doCheck” comes. “DoCheck” is a hook of events that is watching all the events in the components which involve user interactions. It refreshes again the entire component tree where an event occurred (an input field has changed, a click on an element in the document, etc.) and, as a consequence, the values in the views are updated; including those pointed by memory references. It does not matter if they have changed or not. Of course, the “doCheck” does not work when the component change detection is configured with “onPush”, which greatly improves the performance of the application due to the lower number of renderings that are executed.

The solution:

We want our app to be as efficient as possible so we decided to configure the change detection of all our components in “onPush” mode. However, still the problem that the view is not updating when the input of the components is an object. There are two solutions. The first one is using immutable objects as input parameters. It forces to change the memory references each time the value changes so the onChange event can see the modification and update the view. But it is an article about reactive programming so let’s see how we can solve this problem with observables. Take a look at my solution:

As you see, I’ve got the input element of the template using the template reference of Angular. After that, in the hook OnInit, I create an observable from the event ‘keyup’ of the input. Basically means that, each time the user releases a key to write on the input an event next is happening in the observable. This observable transforms the event value in an object using the operator map and the result is passed as input into our “onPush” component. The subscription and unsubscription of the observable is managed by the “async” pipe which is also the responsable to get the value inside the subscription.

Obviously this solution works but the question is why it is working. I mean… to update the view, we need to render the template but the input still an object, a memory reference, the “onChanges” would not have to work. The DoCheck is down because the component is in “onPush” mode… Why is the view rendered? Take a look at the next experiment:

This code takes the value of the initial object and creates an observable with it. In the map operator, it takes this value and create another object equal to the initial … or at least it seems the same. In the subscription I make a comparison between the result of the observable and the initial object and … surprise! … They are different.

This is because, when we create a new object, we are creating different memory reference that points to the new value. In the end, a new reference means a different entry which can be detected by the “onChanges” hook. The “onChanges” refreshes the view and the values are updated. It is that how it works. As you can see in the link of the solution in stackblitz, the counter of the renders only increases one per key pressed, so this solution is more efficient than the default change strategy.

Until the next time:

I do not know what your opinion is about this solution, but for me it seems quite natural … I mean, I created a data stream using observables which carries the information and takes it to the component where it should be. It is one of the reactive programming features; to create data routes … and it’s just the beginning. In my next article, I will show how a redux architecture can be encoded without a boilerplate code.