Thank You, RxJS!
- Published on
Now, what is RxJS and how is it used in Angular?
First of all, RxJS isn't a framework. It's a library for holding asynchronous data streams using reactive programming concepts. It's like React, which is library but for building user interfaces (This is a common misconception about React, don't worry!). I'll also be taking note of writing a blog about this too! 😄
RxJS works well with Angular because the latter often handles many asynchronous data from different data sources. RxJS provides a way of handling these actions better.
So, what was my problem?
Earlier, I mentioned how I was challenged on fixing a certain bug that creates a server error whenever a button was clicked a lot of times. Imagine, a kid who unintentionally uses his elder sibling's account and spams the refresh button on the app and this button calls the server to check on updates. The server then complains how it's getting a lot of requests in such a short span of time. Now, we don't want that to happen don't we?
The fix was simple — RxJS!
I researched on which RxJS operator I could use in order to solve this bug. And there it was — debounceTime.
According to the RxJS Website, debounceTime allows an observable to emit data after a particular time span has passed. In other words, even though the kid keeps spamming the refresh button - the server call would only happen after x seconds, making it impossible for the server to receive many requests.
In addition, debounceTime will pass the most recent notification every x seconds.
Consider this faulty code:
public refreshPage(){
this.functionThatCallsServerForSomeNewData();
}
and in my HTML:
<button (click)="refreshPage()"> Refresh </button>
This would make the server receive too many requests if someone were to spam the button.
Consider this fix:
private refreshPageBtnSubject$ = new Subject<void>();
ngOnInit() {
this.refreshPageBtnSubject$.pipe(
debounceTime(200)
).subscribe(() => this.refreshPage());
}
private refreshPage(){
this.functionThatCallsServerForSomeNewData();
}
public onRefreshClicked() {
this.refreshPageBtnSubject$.next();
}
and in my HTML:
<button (click)="onRefreshClicked()"> Refresh </button>
To explain what's happening in the new code, let's take it step by step.
- First, I attach
onRefreshClicked()
on the(click)
event of the button instead ofrefreshPage()
. - Whenever the Refresh button is clicked,
this.refreshPageBtnSubject$.next()
is triggered. What this does is that it emits an event on therefreshPageBtnSubject$
which will trigger the debounceTime and callrefreshPage()
instead of the old approach.- This is like sending a signal to the lines of code within
ngOnInit
but because we putdebounceTime(200)
, 200 ms must pass first before proceeding to callrefreshPage()
. - So if the kid keeps on spamming, the
refreshPage()
will only be called on the latest emission every 200 ms. Goodbye spamming!
- This is like sending a signal to the lines of code within
- Lastly, I changed the access modifiers of
refreshPage()
. Remember, sincerefreshPage()
is now only called whenever there is an event emission inrefreshPageBtnSubject$
, that means that the former is now only used within the class. The same goes withrefreshPageBtnSubject$
. On the contrary,onRefreshClicked()
, is public because it is called outside the class/TypeScript file which is in the HTML file.
There are a lot of ways on how RxJS can be used. There are even a lot of operators categorized based on what they can do. There are operators that combine, filter, transform, create, and catch errors. These are used depending on the use case of a certain problem. I will also write about other operator that I have used in future blogs. For now, I hope you have learned something new today.
Photo by Morvanic Lee on Unsplash