Mastering Hard Parts of JavaScript: Asynchronicity I
Tags: javascript, webdev, async, codenewbie
Published: 2020-08-17 00:37:19

---
series: Mastering Hard Parts of JavaScript
description: An introduction to JavaScript asynchronicity using 10 exercises
---
## The Event Loop

Understanding asynchronicity in JavaScript requires understanding one fundamental concept: what will the JS engine execute next? This is a very simplified overview of how to answer this question, more formally known as the _Event Loop_.

JavaScript is (for the most part) single threaded, so if everything in JavaScript was synchronous, The JS engine would execute every statement one by one as they appear in the source code, wait for the execution to finish, and go to the next line.

However that would be incredibly limiting when it comes to web development. To solve this problem, some APIs that the browser/node.js provide are asynchronous, which basically means that they don't execute when the JS engine first runs into them. Instead they get put in a queue, to be executed once all the synchronous statements have finished. Let's consider:

```js
function printHello() {
  console.log("Hello");
}
setTimeout(printHello, 0);
console.log("Me first!");
```

Because `setTimeout` is told to execute `printHello` at 0 milliseconds, one could reason that the output should be:

```js
Hello
Me first!
```

But in fact the the output is

```js
Me first!
Hello
```

This is because setTimeout is an asynchronous API (a callback function), so its execution gets placed in the "task queue". Anything in the task queue is only executed after all synchronous code has already run.

Note: `console.log` is in fact itself an asynchronous function but I'm glossing over that detail for the sake of simplicity and clear demonstration of the concept.

## Promises

_Promises_, introduced in ES6, add one additional queue to the mix. Consider:

```js
function display(data){console.log(data)}
function printHello(){console.log("Hello");}
function blockForLong(){
    const arr = [];
    for (let i = 0; i < 3_000_000_000; i++>){
        arr.push(i)
    }
 }
setTimeout(printHello, 0);
const futureData = fetch('https://twitter.com/AmeriRyan/status/1291935897076641792')
futureData.then(display)
blockForLong()
console.log("Me first!");
```

This code won't run correctly as this is not exactly how fetch() works, but for the sake of simplicity, let's assume that `fetch` is a function that takes a URL as a string and returns a Promise. `blockForLong` is a function that doesn't do anything important for our purposes but is a synchronous function that takes a long time to execute. We first call `setTimeout` that runs `printHello` at 0 milliseconds. Then we handle the Promise and pass it to a function `display` that just prints it to console. Then we execute `blockForLong` and finally we execute `console.log`. Can you guess what gets printed first?

First, all synchronous code is executed. That means `blockForLong` is called first, and then `Me first!` is printed to console. Promises get placed in a queue called the "micro task queue", which has priority over the "task queue" where callback functions are placed. So even though `setTimeout` appears first in the source code, we first call the `display` function with the returned data, and only call the `printHello` function last.

So, the _Event Loop_ in JavaScript, in a nutshell, is:

1. Synchronous code
2. Anything in the micro task queue (Promises)
3. Anything in the task queue (callback functions)

If you can follow the execution order in the this example, you should be able to solve all the upcoming exercises (perhaps with a bit of help from MDN).

In the next section, we'll practice 10 exercises that should help us master asynchronicity as well as introduce us to Promises.