Over a million developers have joined DZone.

Functional Programming as the Pillar of Reactive Programming

DZone's Guide to

Functional Programming as the Pillar of Reactive Programming

In this excerpt from Luis Atencio and Paul Daniels' book "RxJS in Action", the two authors discuss the influence of functional programming on reactive programming. Read on for more detail.

· Web Dev Zone ·
Free Resource

Have you seen our HERE Twitch channel to livestream our Developer Waypoints series?

This article was excerpted from the book RxJS in Action.

Functional programming is a software paradigm that emphasizes the use of functions to create programs that are declarative, immutable, and side-effect-free. Did you say immutable? The notion of a program that doesn’t ever change state is a bit mind bending. After all, that’s why we put data in variables and modify them to our hearts content. Take the example of a clock. When a clock goes from 1:00 pm to 2:00 pm, it’s undoubtedly changing, isn’t it? To frame this from a functional point of view, we argue that instead of the clock mutating every second, it’s best to return new clock instances every second. Theoretically, both would arrive at the same time.

RxJS borrows lots of principles from FP, particularly in terms of function chaining and lazy evaluation, which are the two design decisions that drive the development of RxJS stream programming. Before we dive in, we’ll explain the main parts of the FP definition we just gave, and then show you a quick example involving arrays.

Functional programs are:

  • Declarative: Functional code has a very peculiar style, which takes advantage of JavaScript’s higher-order functions to apply specialized business logic. As you’ll see later on, function chains (also known as pipelines) describe data transformation steps in a very idiomatic manner. Most people see SQL syntax as a perfect example of declarative code.

  • Immutable: An immutable program (and by this we mean any immutable function, module, or whole program)  is one that never changes or modifies data after it’s been created, or after its variables have been declared. This can be a very radical concept to grasp, especially if you come from an object-oriented background. Functional programs treat data as immutable, constant values. A good example of a familiar module is the String type, as none of the operations change the string they operate; rather, they all return new strings.

  • Side effect free: Functions with side effects depend on data residing outside of their own local scope. A function’s scope is made up its arguments and any local variables declared within. Interacting with anything outside of this like reading a file, writing to the console, rendering elements on an HTML page, and others, are considered side effects and should be avoided or, at the very least, isolated.

Want to learn more about functional programming?

JavaScript’s Array object has a special place in functional programming because it behaves as an extremely powerful data type called a functor. In a simple sense, functors are containers that can wrap data and expose a mapping method that allows you to immutably apply transformations on this data, as seen by the Array.map() method. RxJS streams follow this same functor-like design.

Now, what does this have to do with RxJS? RxJS is inspired by functional programming. Just like you use map, filter, and reduce in arrays, streams are containers that you can use to lift data or events into them, so that you can apply sequences of operations until reaching your desired outcome. Fortunately, you’re very familiar with this concept already by working with arrays. I can lift a value onto an array and map any functions onto it. Suppose I declare some simple functions on strings like to Upper, slice, and repeat:

Functional programming is a huge subject to cover. For more information, you can read Functional Programming in JavaScript (Manning 2016) by Luis Atencio.

Despite being dynamic, streams are actually immutable data types. Once a stream is declared to wrap an array, listen for mouse clicks, or respond to an HTTP call, you can’t mutate it or add a new value to it afterward. You must do it at the time of declaration. Hence, we’re specifying the dynamic behavior of an object or value declaratively and immutably.

['rxjs'].map(toUpper).map(slice(0, 2)).map(repeat(2)); //-> 'RXRX'

Another design principle of streams that’s borrowed from functional programing is lazy evaluation. Streams sit idle until a subscriber (a consumer) is attached to it, only then will it emit the values 1 – 10 in this short example:

Rx.Observable.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

When a subscriber begins listening, the stream will emit events downstream through the pipeline from the producer to the consumer. This is beneficial in the event that your functions have side effects because the pipeline runs in a single direction, helping you to ensure the synchronous order of your function calls.

Lazy evaluation is also important when dealing with infinite sets of data. This is actually a mandatory requirement for streams because they emit data infinitely to handle mouse movement, key presses, etc. Otherwise, buffering the entire sequence of mouse movements in memory could make your programs crash. Without lazy evaluation, code like this will cause the application to run out of memory. We’ll show some use cases of infinite streams:

Rx.Observable.range(1, Number.POSITIVE_INFINITY)

Rx.Observable.fromEvent(someElement, 'click')
   .map(e => [e.clientX, e.clientY])

Streams in RxJS respect JavaScript’s Iterator protocol and subscribers of this stream will listen for all of the events contained inside of it. Iterators are key to generate/process inifite amounts of data. They are also great at decoupling the iteration mechanism, and data being iterated over, from the business logic. When data is separated from the code that acts on it, this is known as data-driven code. With all this in mind, let’s tackle a simple real-world example with RxJS.

Tackling a real-world problem with RxJS

We’ll be working within the domain of a simple banking application that provides users the ability to search for their accounts. This will allow the user to easily find the account they want to manage. First, we’ll show the vanilla JavaScript (imperative) approach, and then we’ll add the reactive and functional bits to create a much more robust and maintainable program.

To keep things simple, we’re going to use a set of static account numbers as search result candidates (this suggestion text box example won’t be actually performing a web search now). Here’s our static data set:

var testData = [

With this data set, you can visualize the execution of this program as the following:

Image title

To implement this, we’re going to need HTML elements for the search box and a container to show results. As the user types into the search box, any results will get inserted into this container:

const searchBox = document.querySelector('#search'); //-> <input>
const results = document.querySelector('#results');  //-> <ul>

This code shows a possible implementation of a smart search box using a typical imperative or procedural solution. The goal of this code sample is to illustrate how you would typically approach this problem without thinking in terms of functional programming and streams. Building a smart search box involves binding the keyup event and using the value in the textbox to look up possible search results. For simplicity, we’ve just dealt with results that match the beginning part of search term. If there’s a match, the results are appended to the DOM; otherwise, the DOM is cleared. For this we created two functions clearResults() and appendResults(), respectively.

searchBox.addEventListener('keyup', function (event) { //#A
   var query = event.target.value;
   var searchResults = [];
   if(query && query.length > 0) { 
      for(result of testData) {  
        if(result.startsWith(query)) {
   if(searchResults.length === 0) { 
   else {
      for(result of searchResults) {
        appendResult(result, results);   

function clearResults(container) {
  while(container.childElementCount > 0) {

function appendResult(result, container) { 
    var li = document.createElement('li');
    var text = document.createTextNode(result);

Running this code generates the following output: If I type “4” into the text box, it will suggest two possible account numbers: “4111111111111111” and “4342561111111118.” Additionally, typing “1” into the box will filter down the results further to just “4111111111111111.” Conceivably, the user could also have typed “savings” and gotten to this account as well. Here’s a simple visualization of this simple state machine in figure 2:

This code shows that creating even this very basic program in vanilla JavaScript requires the use of several state variables, a couple of for-loops, if/else blocks, and updating the DOM. All of these artifacts add complexity to your code. Remember that loops are mutable as they update loop counters. Conditional blocks split your program’s control flow, thereby making your unit tests harder to write. Also, this program is not extensible because virtually all business logic and IO reside within the single callback handler. Imagine that instead of working with test data, we want to fetch results from the web asynchronously later on; the amount of refactoring would force you to almost rewrite this application from scratch.

Certainly there must be a better way! Fortunately, RxJS comes to the rescue. First, we need to understand what the inputs and outputs of this problem are, these will help us build up our event pipeline or stream. At a high level, we can visualize the RxJS solution with a figure, which contains the three main parts producer, pipeline, and consumer.

Image title

On the input side (producer), the user generates raw character codes which we map to numbers. On the output side (consumer), we are receiving a list of potential search terms that match the accounts the user has already typed. But what happens in the middle? This is where the business logic resides and given what we know about streams, we will create a flow in one direction from the input to output (or producer to consumers) by wrapping the same “keyup” event, this time with an Observable.

As JavaScript is built entirely on an event-loop, it’s little surprise that much of the interaction code is built using event handlers, just as we did in listing 3. For keyboard event handlers, each time a key is pressed and released, each handler should expect to see an event. We can plot those events on a timeline as well, and this is the diagram style we’ll be using to explain streams, known as “marble” diagrams:

Image title

The Rx approach will be similar to the above and behind the scenes still uses JavaScript’s event system, but implemented under a different paradigm. Thinking reactively, the first thing we notice about the series of keystrokes is that they all follow, one after the other along the time line. The key presses themselves are nothing more than sequences of events over time, as shown with marbles in the figure above.

Each item corresponds to a single discrete event, initiated by the user but visible to us as a single orderly flow of time. These events will undergo a series of transformations in a step-by-step manner. At each step, the data is received, processed and handed down to the next step, sequentially. An Observer further downstream would no longer see the individual numbers floating by, detached and without context. Instead, they would see the partial search results generated within the pipeline. In other words, observers see the result of applying the business logic over the data that passes through. Let’s look at the reactive solution now in listing 2. It uses the same functions clearResults and appendResult, but completely decouples the business logic of capturing the event value, fetching the suggestions, and then processing and displaying the results.

const search$ = Rx.Observable.fromEvent(inputText, 'keyup') 
  .map(event => event.target.value)  
  .switchMap(query => Rx.Observable.from

search$.forEach(result => { 
   if(result.length === 0) {
   else {
      appendResults(results, result); 

function findAccounts(query) {
   return testData.filter(item => {
      return query.length > 0 && item.startsWith(query);   

This code uses some advanced RxJS APIs. More importantly, notice that the business logic was completely streamlined and shortened. Also, it was separated from event subscription mechanism, and flattened out in a sequence of steps that transform the contents of the stream. The functions that contain the side effects of reading and writing to the DOM were also isolated as part of the Observer logic.

We also made other improvements along the lines of functional programming principles, like eliminating the loops from the function that finds the suggestions. Instead, we used Array.filter() to remove unwanted suggestions. Streams can also be mapped and filtered in the same way arrays can. The RxJS library encourages this style of development and in best programming practices where functions are simple and perform exactly one task—the Singularity principle of functions. Then using Rx.Observable, you can chain together these operations that individually don’t have much use, but together implement the most complex solutions.

As we’ve mentioned previously, reactive programming is founded on functional programing principles. Using both yields a combination called Functional Reactive Programming (FRP). FRP can be superior to plain reactive programming because you’re essentially adding an extra layer of protection to your code that guards it against the types of problems that derive from accidental side effects and mutations. Through the Observable object, RxJS guards the event data passing through it from inadvertent mutations and forces you to to call or “map” functions onto the observable in order modify the internal data in an immutable way. This is achieved by creating new observables at each step in the pipeline. Also, this sequential application of functions acts like a conveyor belt that orchestrates the execution of the functions in the pipeline, so as to minimize (to some extent) the possibility of functions with side effects colliding with each other. Because functional and reactive programming don’t use imperative artifacts, we don’t use standard flowchart notation to model the business logic executed within the pipeline; rather, we rely on marble diagrams, as shown in the following graphic:

Image title

The pipeline is a sequence of downstream operators through which the event data gets transformed, creating new streams along the way that finally conclude with the account suggestion data as streams that the observers see. Observers will never see the initial key strokes; they see the final processed data. All of this happens over time as the events are emitted.

In practice, most people use FP to the extent that RxJS requires you to, but leave the rest of the application and business logic in an imperative style.

Now, we’ll add the extra bits of functional programming to refactor the remaining functions. We do this in order to create code that reduces mutations and side effects as much as possible. Both allow us to build more maintainable and robust code.

There’s no particular order to refactoring this code. The first change we’ll make will be to remove the while-loop from clearResults and just rely on functions to take care of the iteration for us. This is typical of functional programs that use recursion as the default looping mechanism so that you’re free from updating loop counters. For HTML documents, recursion is a natural approach to traversing them:

function clearResults(container) {
  if(container.childElementCount !== 0) {  

Next is to eliminate all side effects from our code. The findAccounts function in listing 2 accesses testData, which is external to its scope. So, we’ll refactor it by explicitly declaring parameters that take the array as well as the query term to filter by. Now this function has provided everything it needs to achieve its purpose. We’ll rename it to also reflect this fact:

function findAccountsInArray(arr, query) {
  return !arr ? [] : arr.filter(item => {
    return query.length > 0 && item.startsWith(query);   

With this small change, this function is not as easy to plug into the pipeline as before because it now requires that we pass two arguments instead of one. Of course, I could have used the closure formed around the observable declaration and directly embed testData array as part of the stream declaration:

Rx.Observable.from(findAccounts(testData, query))

But this is also a side effect. For instance, if testData gets deleted or changed by another part of the program or even by another function within the pipeline, the whole stream could break. We want to take advantage of the error-checking code in findAccountsInArray. I can fix this by partially binding arguments onto this function using JavaScript’s bind() method on the function prototype, creating our new findAccounts function

const findAccounts = findAccountsInArray.bind(null, testData); 

While the stream declaration stays exactly the same as in listing 2, this program has no side effects. Also, this will allow us to easily swap the synchronous findAccounts() with, say, an asynchronous findAccountsHttp() later on and our program will work exactly the same way. This is the beauty of RxJS as we alluded all along: it’s a single programming model, for any type of stream, and it leverages functional programming to gain modularity and extensibility. Again, the goal is always to eliminate and reduce mutations and dependency on external data as much as possible. You want your functions to be closed components, rather than open ones.

In RxJS, we will always have a pipeline that takes data from the source to the corresponding consumer. Data will always be created or materialized from a data source. Again, the type of data source is not relevant to how our abstraction of a data source operates. Likewise, when data reaches the end of its journey and must be consumed it is immaterial where the data came from.

We’ll reiterate that the separation and abstraction of these two concepts, data production and data consumption, is important for two reasons:

  1. It enables us to hide differences of implementation behind a common interface, which lets us focus more on the business logic of our task. This has the benefit of not only optimizing development time but also reducing code complexity by removing extra noise from code.

  2. The separation of production and consumption builds a clear separation of concerns and makes the direction of data flow clear.

Hope you've enjoyed this article! A treatment of the most useful and powerful RxJS 5 APIs, as well as touch on Functional Programming techniques is covered in RxJS in Action.

Developer Waypoints is a live coding series from HERE, which will teach you how to build with maps and location data.

javascript ,streams ,functional programming ,rxjs ,reactive ,reactive extensions

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}