The core.async library
If you've ever done any amount of JavaScript programming, you have probably experienced callback hell. If you haven't, the following code should give you a good idea about what it is:
http.get('api/users/find?name=' + name, function(user){ http.get('api/orders?userId=' + user.id, function(orders){ orders.forEach(function(order){ container.append(order); }); }); });
This style of programming can easily get out of hand. Instead of writing more natural, sequential steps to achieve a task, that logic is instead scattered across multiple callbacks, increasing the developer's cognitive load.
In response to this, the JavaScript community released several promises libraries that are meant to solve this issue. We can think of promises as empty boxes we can pass into and return from our functions. At some point in future, another process might put a value inside this box.
As an example, the preceding snippet can be written with promises, like so:
http.get('api/users/find?name=' + name) .then(function(user){ return http.get('api/orders?userId=' + user.id); }) .then(function(orders){ orders.forEach(function(order){ container.append(order); }); });
The preceding snippet shows how using promises can flatten your callback pyramid, but they don't eliminate callbacks. The then function is a public function of the promises API. It is definitely a step in the right direction, as the code is composable and easier to read.
As we tend to think in sequences of steps, however, we would like to write the following:
user = http.get('api/users/find?name=' + name); orders = http.get('api/orders?userId=' + user.id); orders.forEach(function(order){ container.append(order); });
Even though the code looks synchronous, the behavior should be no different from the previous examples. This is exactly what core.async lets us do in both Clojure and ClojureScript.