What is RxJS? According to the documentation, “RxJS is a library for composing asynchronous and event-based programs by using observable sequences.”
What does that mean? Think of RxJS as a way to manage data as it flows through time, similar to how Apple’s flow on a conveyor belt. First we collect. Apples are picked, hauled and loaded onto a conveyor, creating a stream of apples. Similarly, we use RxJS to send an HTTP request and receive the response, creating a stream of data. The stream is observable. We can watch it as items are added or emitted to the stream. We pipe the stream of apples through a set of operations. As each apple flows through, we transform the apple by cleaning it, filter it by quality or size, and process it of fixing a label, for example. Likewise, we pipe our data through a set of operations to transform, filter or process our data. Using query like operators, we combine streams to merge their results. In our apple example, we combine the green apple stream with a red apple stream to create a mixed bag of apples. Correspondingly, we combined a stream of customer data with the stream of invoice data to display a customer with their overdue invoices, and we can cache the stream. This one doesn’t fit as well into our apple metaphor. But when working with data, we may want to cache it in a service to reuse the data without another HTTP request.
Going back to the definition, we restate this as “RxJS is a library for composing observable streams and optionally processing each item in the stream using an extensive set of operators.” RxJS helps us better manage and manipulate the data needed in our application. There are other techniques for managing asynchronous and event-based data.
A callback is a function that can be called back after an async operation is complete, but callbacks can be difficult to manage when working with nested async operations.
A promise is an object that may produce a single value sometime in the future. It can only handle a single emission and is not cancelable.
async/await is a special syntax that allows writing asynchronous code that looks synchronous. It also can only handle a single emission and is not cancelable.
Why use RxJS and not one of these approaches? Using RxJS has several advantages. RxJS provides a single technique for working with any type of data. We often work with multiple sources of data. Events from the keyboard, mouseover routes and data from various files, databases or third party APIs. With RxJS, we work with different data sources using the same techniques and operators. Our views often require data combined from several sources. We easily compose data with RxJS. RxJS can produce multiple values over time and uses a push model to notify our code when specific actions occur, making it easy for us to watch and react to user interactions or data changes. RxJS is lazy. Evaluation does not start until subscription. So we can create recipes that only execute when we need the result. For the best user experience we want to handle errors gracefully. RxJS has built-in error handling and with RxJS we can cancel asynchronous actions. For example, if a user clicks on Product A and then quickly clicks on Product B, we can cancel the request for Product A and only return Product B.
So many great advantages to RxJS that Angular built it in into several key features. For example, Angular uses RxJS in routing to watch for changes to route parameters, route data or router events. In Reactive Forms to watch for value changes as the user modifies input elements on a form and when communicating with the backend server, sending requests and receiving responses using HTTP client. That’s why Angular installs RxJS as part of its core set of libraries. We can expand our use of RxJS in our Angular applications to move towards more Reactive Development.
What is Reactive Development?
From Wikipedia, Reactive Development, also called Reactive Programming, is a declarative programming paradigm concerned with data streams and the propagation of change. As the user makes a selection, data is retrieved from a backend server or some other system status changed. That change is propagated and the application reacts appropriately updating the display or performing another action. In addition, reactive development is functional.
“The essence of functional reactive programming is to specify the dynamic behavior of a value completely completely at the time of declaration.” – Heinrich Apfelmus.
A reactive system is quick to react to user interactions, resilient to failure with good error handling and reactive to state changes, meaning the code watches for change events and reacts, instead of procedurally calling methods.