Posted on by & filed under Content - Highlights and Reviews, Mobile Development.

There are surprisingly many parallels between managing callback hell and functional programming. This article will lead you through common pitfalls involved with writing asynchronous JavaScript and will demonstrate how functional programming techniques make these pitfalls disappear.

We shall investigate an example of messy code and see existing control flow solutions that clean up the messy code. We will then look into a partial function application and function composition and see how those techniques apply to clean up the messy code.

Callback hell

Callback hell is the phenomenon where you end up with a lot of nested functions and a high level of indentation. This commonly happens when you use a lot of in-line function expressions. Callback hell is common if you’re writing code with node.js, which generally involves a lot of asynchronous callbacks or if you’re using something in the browser and using nested event handlers and ajax calls.

Let’s take an example from

The code above is actually a list of asynchronous actions that need to happen in the specific sequence. You could be tempted to refactor the code using a library like seq to represent it as a sequence of actions:

Alternatively you could recognize that it’s actually a waterfall of actions that need to occur. Then you would use a library like async to represent the code as the flow of a waterfall:

Or taking advantage of the function signature match:

Both of these solutions represent the original code as something that doesn’t suffer from callback hell. The main advantage here is the lack of indentation and the more linear appearance of the code. In general using a control flow library like seq or async makes the code more maintainable.

However, the issue with these libraries is that they hurt readability unless you’re familiar with them. Specifically the concept of a sequence or waterfall does not come naturally to JavaScript. Another issue is that these types of control flow libraries make it to easy to turn your code into something that looks like a DSL (There are actually real DSLs for managing control flow like streamline).

Functional programming

Now you might ask the question, where does functional programming come into this? I hear your sentiment, let’s take a look at the notion of partial function applications. A partially applied function is a function that has some arguments frozen in place. We can use ap to demonstrate this using examples:

addFive is a partial application of sum. It’s a version of the sum function which has the first argument frozen as the value 5.

Then when we call addFive(10) it’s actually equivalent to calling sum(5, 10) so returns 15.

We can use partial function applications to simplify the example we had.

When trying to apply partial function applications to our example we actually see they are not necessary when we use function declarations. You can also see that the function declarations are in order. It turns out that the seq, waterfall and partial application abstractions are not needed when we express the coded as function declarations. Let’s take a look at an example which does actually need partial function applications to work (without error handling code for brevity):

The above example has the client variable used in the last function which isn’t a parameter. So we can’t just split this out into function declarations and have it just work. However we can use partial applications:

What we are doing here is effectively taking variables that we used to reference through closures and freezing them in the parameter list of a function. In the above example we pass the client variable through two functions.

Function composition

However we can do better then this when we recognize that the above code is actually a composition of numerous functions in an asynchronous manner. Let’s look at a simple example of function composition using composite.

Composition takes a number of functions and returns a new function that applies each function onto the input in order. If we redefine the return value of a function as calling the last argument (the callback function) with (err, result) we can actually generically compose asynchronous functions together.

What we’ve done above is described the action we want to take as a composition of the four individual function calls. We have also called the function with a specific thisValue which is used in all calls. This allows us to store temporary values on the thisValue.

Although using asynchronous function composition might look similar to using seq or waterfall, the difference is that we are using a well known functional programming technique to reduce the complexity of our code instead of bringing in a library whose specific purpose is “control flow.”

There are other functional programming techniques like map, filter and reduce that we can also use to make asynchronous programming easier. We will look at these in the future.

Safari Books Online has the content you need

Take advantage of these Node.js resources in Safari Books Online:

Node: Up and Running (Rough Cuts) introduces you to Node, the new web development framework written in JavaScript. You’ll learn hands-on how Node makes life easier for experienced JavaScript developers: not only can you work on the front end and back end in the same language, you’ll also have more flexibility in choosing how to divide application logic between client and server.
Read What Is Node? to get up to speed on Node.js with this concise overview.
Node for Front-End Developers shows you how to use this popular JavaScript framework to create simple server applications, communicate with the client, build dynamic pages, work with data, and tackle other tasks.
In Sams Teach Yourself node.js in 24 Hours, expert web developer George Ornbo guides readers through every step of creating custom server-side solutions with Node.js.

About this author

Jake Verbaten is a JavaScript evangelist and open source hacker. He’s published a ton of modules on npm and build multiple production applications using node.js. To learn more about Jake, check out his github profile.

Tags: asynchronous, callback, Filter, Functional programming, Javascript, map, Node.js, reduce, refactor, waterfall,


  1.  Functional Programming: Controlling Parallel Code | Safari Books Online's Official Blog