The Async Series: Callbacks
Tags: beginners, codenewbie, webdev, javascript
Published: 2021-08-08 03:57:31

# Introduction

One of the most infamous gotchas in JavaScript to beginners is the idea of asynchronous programming. This series is all about demystifying async in JavaScript.


# What does Async mean?
Most of the code we write execute sequentially or synchronously. That is execute line 1 then line 2 then line 3.

For example, the following are all synchronous function calls. You can only perform one of them at a time. If you are showering then you can safely assume the wake up task has been fully completed.

```javascript
wakeup()
eatBreakfast()
takeShower()
```

However, in JavaScript some function calls are executed **concurrently**. This means the browser would actually switch between them so they appear to make progress simultaneously.

For example: from the moment you wake up in the morning, you start seeing. Then, you may also start moving and at some point you will eat. You might even do all three at once! Note, even though you started seeing before you started eating, the eating task will be completed before the seeing one. This in essence, is how asynchronous function calls behaves.


```javascript
see()
move()
eat()
```

Because of this, a series of asynchronous function calls may finish their execution in a different order than they were started. Often this can be a point of frustration to new programmers when a particular order is desired.

# Why does this happen?

While it is not a hard requirement, if you'd like to get an appreciation as to why this happens in the first place; you can take a look at my post on the JavaScript runtime.

{% post https://dev.to/snickdx/what-is-the-javascript-runtime-4n09 %}

# Async Code in Action

I have three asynchronous functions printBlue/Green/Red. They will all be executed concurrently but each has a different execution time. Green is fastest then red then blue. So if they are called like this.

```javascript
printBlue("Blue");
printGreen("Green");
printRed("Red");
```
Output:

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7xl0vs0pmvxpy256c7k6.png) 

The output is: Green, Red, Blue. The diagram below visualizes the timing of these functions.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t7cpk5noka9w8x3fpuq9.png)

# Getting into flow

Because of their individual execution speeds, the functions finished in a different order than they were called printing "Green", "Red" then 'Blue". However, we want to print "Blue", "Green" then "Red" how do we fix this?

In programming, [control flow](https://en.wikipedia.org/wiki/Control_flow#:~:text=In%20computer%20science%2C%20control%20flow,from%20a%20declarative%20programming%20language.) is the concept of enforcing the order of execution of statements. In JavaScript, one way in which we give the developer the ability to achieve this is to have our asynchronous functions accept **Callback Functions**.

A callback function is a function C that we pass to another function A (often async) such that C is executed by A only when the main work of A is completed. 

Function A is also said to be a [higher-order](https://en.wikipedia.org/wiki/Higher-order_function) function due to the fact that it has another function as a parameter.

Luckily our print functions do accept callback functions so we can create some helper functions that does our desired printing. Then, pass our helper functions as callbacks.

```javascript
//helper function 1
function doPrintRed(){
  //calls print red with our desired parameter
  printRed('Red');
}

//helper function 2
function doPrintGreenRed(){
  //calls printGreen with our desired parameter 
  //then passes doPrintRed as a callback
  printGreen('Green', doPrintRed);
}

//call printBlue then passes do doPrintGreenRed as a callback
printBlue("Blue", doPrintGreenRed);
```

However, this is needlessly long. As we have no use for our helper functions outside of passing them as callbacks, we can make use of **anonymous functions** instead. 

Anonymous functions are nameless function definitions that can be written anywhere a function can be referenced. For example instead of writing doPrintRed we can provide an anonymous function in doPrintGreen.

```javascript
//helper function 2
function doPrintGreenRed(){
  //calls printGreen with our desired parameter 
  //replace reference to doPrintRed with an anonymous function
  printGreen('Green', function(){
      //calls print red with our desired parameter
      printRed('Red');
  });
}

//call printBlue then passes do doPrintGreenRed as a callback
printBlue("Blue", doPrintGreenRed);

```
We moved doPrintRed's code into an anonymous function and passed it to printGreen as a callback. Hence the second parameter of printGreen is called an **anonymous callback function**.

You can then repeat the process for doPrintGreenRed to attain the following.

```javascript
//replace reference to doPrintGreenRed with an anonymous function
printBlue("Blue", function(){
   //calls printGreen with our desired parameter 
   printGreen("Green", function(){
     //calls print red with our desired parameter
     printRed("Red");
   });
});
```
The callback function passed printBlue() calls printGreen(). printGreen() in turn also receives a callback function which then calls printRed(). printBlue/Green/Red are designed in a way such that the callbacks they receive are only executed after printing to the screen.

This is the output:

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3wmk7p6jrbj11hrr1iww.png)
 
The execution now looks like this.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6jrfuf00i93ngp57fp1d.png)

This is because the innermost function must wait on an outer function to execute, and that outer function must wait on another outer function to begin execution.

# Writing Higher-Order Functions

It is up to the author of the asynchronous function to design the function to accept a callback, execute the callback with an appropriate value and explain it via documentation. 

Below is a simple implementation of a higher-order add function that receives a callback function.

```javascript
function add(a, b, callback){//allow a callback to be passed
  let answer = a + b;//perform calculation
  callback(answer);//pass the output of the calculation to the callback
}

add(4, 5, function(result){
 console.log("The result is", result);
});//Output: The result is 9

```
The function add() computes a sum and passes the result to a function parameter passed to add(). Higher-order functions such as add() may not return a result but instead ask for a function to pass the result to. 

The example code is available at this [REPL](https://replit.com/@Snickdx/async-1#index.js) so you can try it out yourself.

# Conclusion
And that concludes the intro into asynchronous JavaScript. Many JavaScript APIs are asynchronous including fetch(). Getting to grips with this fundamental concept would serve you well on your journey.