Implement a Countdown Timer with RxJS in Angular
Surely such a task is not super complex and everyone who has worked a little with Angular and RxJS should be able to master it. But I actually like such little tasks to fiddle around with and/or just to see how others solve them. So thanks Mwiza for your article. 👍
But though Mwizas solution works, I don’t find it convincing in detail, especially when using RxJS and Angular we should always take the async pipe into consideration, instead of taking values out of observables just to bind them to HTML. So here is my suggestion.
Bundling the timer components instead of individual properties
First of all, I implemented an interface that describes an object structure that bundles the individual components of our timer (days, hours, minutes and seconds). Interfaces have no meaning for the actual logic, but are a core principle of TypeScript.
The interface can ultimately be placed anywhere (seperate file or in a components file). Since the task here is very simple and is only for demonstration purposes, I left the entire TS code in app.component.ts file in my Stackblitz example (https://angular-countdown-rxjs.stackblitz.io). Feel free to place it where ever is best for you.
Calculation with no side effects…
In my next step, I placed the entire calculation logic (based on the original) into a single function. As a result, the logic is encapsulated and can easily be placed anywhere (separate file, function in service / component file, method of a service / component class).
The function also accepts other deadline dates as parameter, but this is just a gimmick.
The crucial point is that the function has no side effects, i.e. does not change class members as it happens in the original code, but returns an object with the individual timer components. We previously defined the structure of this object through our interface.
Timer with RxJS…
The component itself is very slim.
As in the original, I also use the “interval” function of RxJS to recalculate the remaining time every second. However, I don’t subscribe anywhere and I don’t change my class properties every second. Rather, I use pipe to change the observable.
For this I use the map operator from RxJS. From my point of view, the advantage is that at no time we have to leave the observable (the stream).
ShareReplay is not required in this case. But I did include it in case we want to subscribe to our timer somewhere else.
The HTML Bindings…
Again, my solution is based on the original. To bind to our observable, however, I use the async pipe from Angular. From my point of view, the advantage is that Angular now takes care of subscribing and unsubscribing itself. In addition, this solution is more robust in my opinion when using different change detection strategies in Angular.
One thing is for sure — the year still has many days. Another thing is for sure — both versions (my and Mwizas) work as intended.
What I’m not sure about is which variant is actually better or whether one is better at all. Since I am not a professional programmer, but only play around with Angular as a hobby, I simply lack the practical experience to judge this.
In any case, I just wanted to introduce the async pipe in this context. So enjoy the rest of the year. 😃