

Discover more from hrbrmstr's Daily Drop
Dearest Reader,
I trust this Drop finds you in good health and high spirits!
I am pleased to inform you that we will be continuing our weekly focus on JavaScript with a brief and achievable introduction to reactivity in the witchcraft known as RxJS. However, due to the code-focused nature of this witchcraft edition, we will have to meet in secret on another website to complete our exchange.
I pray this does not inconvenience you too much, and ask your pardon if it does.
Best Regards,
—hrbrmstr
P.S. This is what you will be building.
Before we get ahead of ourselves… we should talk a bit about what RxJS is, and why you should consider using it. You are welcome to jump straight to the project/code, though (big orange button at the end of this post). We aren’t in the olden days the Drops’ intro would have us believe, and I am fully aware patience is a thing of history.
RxJS is a reactive programming library that is designed to make it easier to work with asynchronous data streams. We called these “events” in the olden days, and often still do. Though, they are much more than simple if-this-then-that triggers. This fancy library provides a wide range of tools and functions that allow developers to “create powerful and flexible data pipelines that can respond to changes in real-time”. I’m not going to beat too hard on this drum, since you already know about ObservableHQ, and have seen this type of processing already. And, you likely know both React and Vue (and, Svelte) give you reactivity. But, you don’t need giant frameworks for basic reactivity, nor do you have to live with banal document.addEventListener
machinations. Plus, I’m all about zero tech lock-in.
Before the rest of the in-newsletter blathering, here’s a pretty simple example of how to switch the good ol’ vanilla js button click handler:
const button = document.querySelector('#myButton');
button.addEventListener('click', () => {
console.log('Button clicked!');
});
into something that sets you up for much more powerful reactivity in RxJS:
import { fromEvent } from 'rxjs';
const button = document.querySelector('#myButton');
fromEvent(button, 'click').subscribe(() => {
console.log('Button clicked!');
});
Apart from the import
, it’s the same amount of code, but the latter warps you into the RxJS galaxy that’s much closer than the one with the cantina Han shot first in.
So, once more: one of the main problems that RxJS solves is the issue of managing complex, asynchronous data flows. By providing a set of composable operators that can be used to manipulate data streams, RxJS makes it easier to build complex applications that can respond to user input and changes in real-time.
Code > Words
While you won’t be making anything this complex (unless you want to) in the WPE, a great example of a problem RxJS can help solve elegantly is the common, modern idiom of providing real-time suggestions in a search/input box.
Let's say we have a search bar on a web page, and we want to display search results in real-time as the user types. In vanilla JavaScript, we might add an event listener to the search input that triggers a search function every time the user types a new character. However, this can quickly become inefficient if the search function is computationally expensive, or if the user is typing rapidly.
With RxJS, along with the basic eventing (we saw this earlier) we have a few more batteries we can plug in to can create an observable that emits an event every time the user types a new character. Then, use RxJS’s debounce powers 💪 to delay the search function until the user pauses typing:
import { fromEvent } from 'rxjs';
import { debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators';
const searchInput = document.querySelector('#searchInput');
const searchResults = document.querySelector('#searchResults');
fromEvent(searchInput, 'input').pipe(
debounceTime(300),
distinctUntilChanged(),
switchMap((event) => {
const searchTerm = event.target.value;
return fetch(`https://my-api.com/search?q=${searchTerm}`);
}),
switchMap((response) => response.json())
).subscribe((data) => {
searchResults.innerHTML = '';
data.forEach((result) => {
const li = document.createElement('li');
li.textContent = result.title;
searchResults.appendChild(li);
});
});
It’s not a ton of code, is pretty readable even if you’re only lightly familiar with javascript, and it demonstrates the eventing plus some built-in functional superpowers that work super well together.
In this example, we use the fromEvent
function to create an observable that emits an event every time the user types a new character in the search input. We then use the debounceTime
operator to delay the search function by 300ms, which helps to reduce the number of requests made to the API. We also use the distinctUntilChanged
operator to ensure that we only search for new terms that are different from the previous search term.
Next, we use the switchMap
operator to map the input event to a fetch request to our API, which returns a response containing search results. We then use another switchMap
operator to convert the response to JSON format.
Finally, we subscribe to the observable and update the search results HTML element with the new search results.
Your Mission
You are going to build a small app that warps between solar systems!
I mean, not really. Fundamental, unbreakable laws of the universe and all that. But, it will give you a small, doable app to look at, break into pieces, then extend (with provided resources and/or your imagination). Essentially, I’m giving you a pre-built, risk-free environment to explore JS in general and also something you can extend to do more with RxJS after you read more about it.
I’m going to have to ask you to head over to GitHub for the remaining details, since code blocks on here are awful.
I’ll FIN it over there as well.
Drop #241 (2023-04-14): Weekend Project Edition
Github link not working for me (404 - Page not found).