Thank You, RxJS!

Published on
codeangular

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.

  1. First, I attach onRefreshClicked() on the (click) event of the button instead of refreshPage().
  2. Whenever the Refresh button is clicked, this.refreshPageBtnSubject$.next() is triggered. What this does is that it emits an event on the refreshPageBtnSubject$ which will trigger the debounceTime and call refreshPage() instead of the old approach.
    • This is like sending a signal to the lines of code within ngOnInit but because we put debounceTime(200), 200 ms must pass first before proceeding to call refreshPage().
    • So if the kid keeps on spamming, the refreshPage() will only be called on the latest emission every 200 ms. Goodbye spamming!
  3. Lastly, I changed the access modifiers of refreshPage(). Remember, since refreshPage() is now only called whenever there is an event emission in refreshPageBtnSubject$, that means that the former is now only used within the class. The same goes with refreshPageBtnSubject$. 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