Async JS Patterns using Callback
Published: 2022-02-01 13:46:21

JavaScript, one of the most used computing programming languages in today's world [[_reference_](https://www.statista.com/statistics/793628/worldwide-developer-survey-most-used-languages/)], very criticized for its simplicity compared with Java or C++, but unquestionably, this is precisely one of the characteristics that makes it as powerful and globally spread.

Along these series of managing JS concurrency, we will discuss about some of the *weapons* we should probably all have in our *personal arsenal* when developing in JS; the main objective of these series is precisely train you in the *combat* *field* using those *weaponry.* 

It is important to highlight that even when there are new fancy ways of solving concurrency problems, each mechanism has it own advantages/disadvantage and use-cases. 

In this first *episode* we will talk about callbacks, a pretty nice initial way of solving concurrent tasks.

> JS engine behaves pretty similar to the electricity, it is always looking for the path with less resistance, it will jump anything that might seem slow (setTimeouts, API calls, rendering etc) and go crazy executing the fastest instructions unless we use mechanisms for dealing with it 😉 (such as callback, thunks, promises, generator functions, async functions).
![Jumping](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/05bs84pmv5boidrg5zmf.gif)

## Callbacks 🤔

It all comes from functional programming where some brilliant guys back in 1930 introduced what is know known as *lambda calculus,* this topic is deep enough to another article but let's continue.

Let's go over the next function, it basically expects two arguments and prints out the sum of those, pretty simple, isn't it?

```javascript
function foo(a, b) {
	console.info(a + b); // 3
}
foo(1,2);
```

But what about sending the reference of a function instead of some variables? - what would happen?

```javascript
// A function for sum
function sum(a, b){
	return a + b;
}

// A function that orchestrates
function foo(callback, a , b){
	return callback(a,b) // this line will call our sum() 
}

const resp = foo(sum, 1, 2) // we pass the reference of the function sum() and two numbers
console.info(resp); // 3
```
Oww we just chained functions in a pretty awesome way, so we could also add a new function _subtract_ so that just changing the reference to the new function, we can either sum or subtract.

```javascript
function sum(a, b){
	return a + b;        
}

// New Subtract function
function sub(a, b){
	return a - b;      
}

function foo(callback, a , b){
	return callback(a,b) // this line will call either sum() or sub()
}

const respSum = foo(sum, 1, 2);
const respSub = foo(sub, 1, 2);  // We can now subtract too!

console.info(` Sum:  ${respSum}` ); // 3
console.info(` Sub:  ${respSub}`); // -1
```

The Callback pattern is very used but it is even more powerful when regarding asynchronicity; hopefully our apps need to communicate with other APIs for fetching, saving, updating data, this brings some new *players in the game;* we need to play with *the mess* produced by the JS engine when trying to execute as many instructions as possible without worrying about 
*sequential/blocking* execution and *human* *reasonability;* dear reader, this is what I call *asynchronicity heartbreak*. 

You can copy, paste and execute the next code and you will see how the JS engine prints ‘Second Line’ first and then ‘First Line’; in the opposite order as we really want.

```javascript
function fetchFoo() {
    setTimeout(() => {
        console.info('First Line')
    }, 2000)
    console.info('Second Line')
}
fetchFoo()
```

What is really happening is when the JS engine executes *fetchFoo*() it will first try to read and solve the first line but as the *setTimeout* is waiting 2 seconds *it jumps* to the next instruction and prints 'Second Line' first.

Theoretically speaking one way of solving this puzzle is manually passing asynchronous tasks as they were synchronous, so that the JS engine doesn't have any other branch of code to prioritize and as soon as it finishes we pass new tasks and so on.  Let’s revise the next code.

```javascript
// Chaining callbacks as a way of forcing sequential execution

function fooBar() {
    cb1()
    function cb1() {

        setTimeout(function () {
            console.info('First Line')
            cb2()
        }, 1000)

        function cb2() {
            console.info('Second Line')
        }
    }
}

fooBar()
```

We are basically forcing a link of consecutive instructions so that the JS engine doesn't even have to think an easier path to follow, it doesn’t have any more option that waiting 1 second and printing the ‘First Line’ and then the ‘Second Line’ as we originally wanted.

The next code is a cleaner and more beautiful approach using the same principle.

```javascript
function fooBar(cb1) {
    setTimeout(function () {
				// The function cb1() expects another callback - the cb2()
        cb1(function cb2 () {
            console.info('Second Line')
        })
    }, 1000)
}

// The function cb1() will eventually read and execute another callback that is not still defined.
// We will eventually define it with the next sequential instructions.
fooBar(function cb1 (cb2) {
    console.info('First Line')
    cb2()
})
```

We are basically saying: hey JS engine, you know what? - I will pass to you another function in a moment, I can not pass it to you right now because you will try to execute it in a way I don't want, so don't worry, just go ahead with your business and I call you later. When the timer reaches the 1 second and the ‘First Line’ is printed, we pass to it a _brand new_ code (with the string ‘Second Line’) to execute, this is basically known as *lazy execution*.

> Callbacks are a mechanism for lazy execution.

As almost everything in life, there are some considerations that need to be carefully taken. When using callbacks we will need to agree with the **inversion of control**, giving the control of our program to somebody else. we have probably all have to invoke an external API using this mechanism and living the horror of expecting that API doesn't fail, simply because there is no way that API notifies us, so that, we can code an emergency exit, we basically loose the _control_ of our program, Kyle Simpson said in a talk regarding callbacks:

> "There's part of my program that I'm in control of executing. And then, there's another portion of my code that I'm not in control of executing."

There is another problem ... **trust**, let's imagine that somehow the _setTimeout_ eventually start failing, sometimes instead of timing 1 second it continues to 100 seconds! - that is a really pain!! - our program will take much longer that what we initially expected, or even worse, image that it never stops !! - Callbacks lack of some sort of mechanism that notifies us when something goes wrong so that we can code an emergency exit and protecting our computer power.

A part of that. there is still another problem with callback, **they don’t match** our sequential blocking way of thinking, Kyle Simpson says in one of his talks: (paraphrasing):

> Bugs arise when code doesn’t work as our brain does. 

Our natural way of solving concurrency problems differ from the way callbacks work, we probably would need another pattern for solving asynchronous tasks that doesn’t force us neither to lose the *control* (inversion of control) of our programs nor the *lack of trust* when third party APIs are involved and by the way, a more *reason*able approach. 

> The real problem with callbacks is deeper than just the *callback hell*

In the next post we will talk about *Thunks*, a slightly different callback pattern.

## References

* [Book] You Don’t Know JS Async & Performance 
* MDN