This article was originally posted on my blog.
RxJs is the implementation of Reactive Extensions for Javascript. These extensions are a collection of tools allowing us to write declarative reactive code as opposed to imperative (e.g. do this when x
instead of if x is this right now, then do the following...
). Basically, it gives us operators (functions) that can enhance handling of event-based logic, especially when working with multiple correlated events.
Rx definitely has a learning curve. New concepts and and terms can be overwhelming at the start. But once you try enough times, eventually it clicks and you get much faster at learning the all the wizzabanga words and concepts. I'll try to keep this post as simple as possible, but you definitely need to be comfortable with the promises API.
Promises vs Observables
Imagine we have an array of strings describing our thoughts.
const thoughts = ["food", "sleep", "code"];
Promise
When we work with events in JavaScript we will typically uses the Promise API. For a promise, two things can happen:
1- It resolves with a single value.
2- It rejects with a single value, usually an error message.
Both 1 and 2 signal the completion of a promise.
const thoughtsPromise = () => {
return new Promise((resolve, reject) => {
resolve(thoughts);
});
};
Observable
An observable is a stream of data from which we can get notifications with values. We can get those notifications in three different scenarios:
1- When there is a new value from the stream.
2- When an error occurs giving us the error value.
3- When the stream is complete.
One difference is that observables can resolve many times with new values. For example, imagine you want to show a video on your app to the user. Would it be better to let the user download the entire video all at once, or to stream it little by little? Observables can help you stream your data.
Let's create an observable.
The from
operator can transform data such as arrays or promises into observables which are streams of data.
import { from } from "rxjs";
// The trailing $ sign is a naming convention for observables in JS
const thoughts$ = from(thoughts);
That's it!
Getting Data
Back to our promise. What do you suppose happens when thoughtsPromise
resolves?
const getValue = async () => {
try {
const thoughtsArray = await thoughtsPromise();
console.log(thoughtsArray);
// Output: ["food", "sleep", "code"]
} catch (err) {
// handle error
}
};
We got the array all at once. And what do you think happens when we start to listen for values, in other words subscribe
to our thoughts$
observable?
// We subscribe to an observable to get values from it
thoughts$.subscribe(
value => console.log(value),
err => null, //handle error,
() => null // handle completion,
);
// Output:
// food
// sleep
// code
We get the values from the array one by one. A stream of data. Cool.
Play with this example (React)
Do I have to know Rx?
Nope. But here are some use cases to consider:
1- To keep code flat in JS if you can't use async await
for some reason.
2- To handle complex event-based logic whether its network related or UI related (e.g. websockets / drag and drop).
3- If your teammates come from different languages but you all know Rx, it might be easier for them to just get going with RxJs than to use promises
and async await
.
4- In other languages, Rx is super useful for handling multi-threading.
5- If you enjoy reactive programming and want to apply it everywhere, go ahead ๐.
Useful links:
- List of Rx operators
http://reactivex.io/documentation/operators.html
- Awesome video on RxJs operators by Fireship
https://www.youtube.com/watch?v=ewcoEYS85Co
- Reactive programming
https://en.wikipedia.org/wiki/Reactive_programming
- Imperative programming
https://en.wikipedia.org/wiki/Imperative_programming
- Declarative programming
https://en.wikipedia.org/wiki/Declarative_programming
- The Observer Pattern
Top comments (0)