Understanding Asynchronous vs. Synchronous Programming in Javascript
Published: 2021-04-11 20:30:47

If you've never been exposed to asynchronous programming before, javascript has functions that are interesting and also annoying if you don't know whats happening. Towards the end of the article, we'll talk about how to turn a javascript asynchronous function, into a synchronous one and how it can benefit us.

The easiest way to think of asynchronous and synchronous programming in a non-programming way is a person who is multi-tasking.

Pretend you are a a barista who is working a morning shift at a coffee shop. This morning you have three tasks you need to complete before you open up the store.
<br>
##### My tasks for this morning:
<ol>
<li>Brew coffee</li>
<li>Clean the counter</li>
<li>Play coffee shop music</li>
</ol>

Now lets see how an asynchronous barista would act compared to a synchronous barista.

| Asynchronous Barista | Synchronous Barista  |
|:-------------:|:-------------:|
| <ul><li>Starts to brew coffee</li><li>While the coffee is brewing, I'll clean the counter</li><li>Coffee is still brewing so I'll get the music started</li></ul>      | <ul><li>Starts to brew coffee</li><li>Waits for the brewing to finish, then cleans the counter</li><li>Finished cleaning the counter so now I'll get the music started</li></ul> |

As we can see in the comparison, the **asynchronous** barista was able to do other tasks while waiting for the coffee to finish brewing. On the other hand, the **synchronous** barista, waited for the coffee to completely finish brewing before moving on to do other tasks.

Now lets translate this back into our Javascript. Although Javascript is a single-threaded language (meaning it can only do one thing a time), it is not fully asynchronous. But Javascript does have functions that are asynchronous. 
An asynchronous function means exactly the same in the barista scenario. When the asynchronous function is called, feel free to do other things until the asynchronous function is done. 

Example:
One asynchronous function in particular is the `fetch()` function that returns a promise. The `fetch()` function can access an api and *fetch* information from it and returns that information as a `Promise`. As you can imagine, depending on the information you try to *fetch*, it might take a while. Since `fetch()`, is an asynchronous function, the IDE will *fetch* this information in the background while doing other tasks, and will get back to the *Promise* when its done *fetching* it.

This is different to a synchronous fetch in which nothing else will get done until the information is fully fetched.

Now you must be thinking, wow Synchronicity sucks! Asynchronous for the win!!

BUT... asynchronicity and synchronicity have their own pros and cons. 
Yes Async sounds super efficient but there are some drawbacks to it that is easily solved by turning this Asynchronous fetch call into a synchronous fetch call. 

Now imagine you need to get a list of items and then display those items onto the DOM. We'd do something like this.

**Warning: This will not work.**
```
function getItems(){
   let list = [];
   fetch('http://localhost:3000/items')
      .then(resp=>resp.json())
      .then(items=>{
      for(item of items){
         new Item(item);
         list.push(item);
      });
   return list
}
// a function to get a list of items^^
// now lets display those items

function displayItems(){
   let items = getItems();
   for(item of items){
      //create element;
      //element.innerHTML(item);
      //document.body.append(element);
   }
}


```

If you've never worked with asynchronous functions before, it might be hard to see the problem here (I spent hours not understanding what was going on). But running `displayItems()` will actually do nothing. 
Wait, but it's getting items from the fetch and assigning the return to a variable. 
Yes but no. We were expecting 'items' to be a list of items returned by the `getItems()` function. Although the main issue is that `getItems()` is making a fetch call which is an asynchronous function. 
This means that by the time the function tries to iterate over the list of items to then try and display each item, the fetch call still has not finished fetching the information which means that the list is empty, therefore we are iterating over nothing.

If you want to give it a shot, run this function and put a `debugger` after the `getItems()` call and right before the for loop. Check the variable items, and you will see that it is in fact empty.

So how do we get around this.
Well in this scenario, the asynchronous function is actually not working in our favor and so therefore we would want to make the function synchronous.

*The asynchronous function was not working in our favor because we want to do things in according to that list that is returned by the fetch call. Meaning that we shouldn't be doing anything else until the fetch is finished.*

So to make our asynchronous fetch call into a synchronous fetch call.
There are two keywords that we'll need to understand in order to do this. `async` and `await`. Using `async` in front of a function declaration will turn the function into an asynchronous function. While using `await` in front of something will wait until that specific thing is finished before moving on.

We'll use these keywords as follows.
```
async function displayItems(){
   let items = await getItems();
   for(item of items){
      //create element;
      //element.innerHTML(item);
      //document.body.append(element);
   }
}
```

The keyword `async` is placed before declaring the function and the keyword `await` is placed right before the thing you want to wait on. 
In our case, this function is now asynchronous but the fetch call is sort of synchronous in this case with the fact that were waiting for the fetch call to be completed before moving on.

Congrats! You finished reading! Hopefully you understand asynchronous and synchronous programming a little better now!

*Side note...* `.then()` *works like* `await` *in the sense that .then() waits for the fetch to return the promise before acting on that promise*