DEV Community

Cover image for Asynchronous Javascript
Jimmy Li
Jimmy Li

Posted on

Asynchronous Javascript

Introduction

Hello Reader, welcome to my first ever blog! This blog begins a series of blogs that I will be writing as I go through my Software Development journey as a student at Flatiron School. Today, I will be talking about Asynchronous Functions in JavaScript and the struggle that I had implementing such a function while working on my Phase 1 Project. But before we get into the nitty gritty of my issue, I would like to first introduce to you what Asynchronous means in JavaScript.

So what does Asynchronous mean in JavaScript?

When we think about doing a task in a synchronous way, what do you typically think of? For me, I usually think about the analogy of a fast-food restaurant where only one worker is present, and that worker has to serve multiple hungry customers. If the restaurant was operating in a synchronous way, the worker would first take the order from the first customer, then he/she would go about making the preparations for that order. For example, the chef would perhaps heat up the stove then after the stove was finished, they would chop some onions, then prepare the patties. The point here, is that the worker would not be very efficient if he was doing each task one after another, and here's where the beauty of doing things asynchronously comes in. Say now, that while the chef is waiting for the stove to finish heating up, he decides to now go chop up some onions and afterwards prepare the patties for grilling. After the chef is done with those two tasks, the stove is now piping hot and he is ready to begin cooking the patties. This is much more efficient we will see in a bit how JavaScript implements this idea in an example I will walk through in the section below.

What is an example of a Asynchronous function in JavaScript?

There are many types of Asynchronous functions in JavaScript, but the one that I would like to highlight today, is the fetch function. Fetch is a special operation that at its most basic level, sends a request to a web server and when it receives a response back, gives you the information that you wanted to retrieve. This is an example of what a GET fetch request is, and there are many more operations that you can perform with fetch. So why is fetch considered a Asynchronous function? I'm glad you asked! I'll demonstrate to you below with a simple coding example.

const msg = "Hello world!"
console.log(msg);
console.log("Before fetch: ")

fetch("https://date.nager.at/api/v2/publicholidays/2020/US")
.then(resp=> resp.json())
.then(data=>console.log(data))

console.log("After fetch: ")
Enter fullscreen mode Exit fullscreen mode

If we have a code block that looks like this, what order would you expect the console.log()'s to be in? If things were happening in a synchronous fashion, we would expect "Hello world!" to be logged first then "Before fetch: ", then "What is 2 + 2?", then the data that we retrieved from the API, then "2 + 2 = 4", then "End fetch: " right? Here is what actually gets logged to the console:

Image description

Amazing right? Since this code block had a asynchronous function within it, JavaScript somehow knew that it would be inefficient for each line to be executed in a set order because once it reached the fetch request, it would wait until it received a response before it executed anything else. So instead, while it was waiting on the fetch request, it went ahead and took care of executing the other lines of code. Much like how the chef would go about doing other tasks while he/she waited for the stove to finish heating up. This idea is especially important when running a website, because if the website was waiting on certain asynchronous things to happen, the website could potentially not even load until it was finished with the asynchronous bits, which would not be a pleasant experience for the user. Now that we have a little bit of background on asynchronous functions and what their usefulness is, I would not like to talk about how I struggled with them during my phase-1 project.

Without getting into too much detail about my phase-1 project, the main thing that I struggled with was how to retrieve information from a fetch request after it is done. For my project specifically, I was trying to retrieve an array that held information that I manipulated from a API called PokeAPI and I was failing miserably at doing so. At first, I simply returned the array after pushing the data that I wanted it to hold, but I realized that when it was console logged, the returned "array" that I set to a variable was empty. I then tried putting return statements at both the places where I convert the response to a JSON format as well as were the fetch was being called, but I got the same result. It wasn't until I reread the course material about asynchronous functions and fetch did I realize where I issue was.

My initial code:

function getResistances(pokemon) {
  //this function will make a fetch request to the PokeAPI type endpoint and push the half damage data to an array
  //and call a separate function to fill that data in a table
  const arrOfTypes = [];
  const resist = [];
  const type1 = pokemon.type1;
  const type2 = pokemon.type2;

  arrOfTypes.push(type1);
  arrOfTypes.push(type2);

  arrOfTypes.forEach((type) => {
    if (type !== null) {
      return fetch(`https://pokeapi.co/api/v2/type/${type}`)
        .then((resp) => {
          return resp.json();
        })
        .then((resistances) => {
          for (let types of resistances.damage_relations.half_damage_from) {
            resist.push(types.name);
          }
        })
        .catch((err) => console.log("failed", err));
    }
  });
return resist; //<-- this does not return the desired array!
}
Enter fullscreen mode Exit fullscreen mode

My issue was that I was thinking about the fetch within my function in a synchronous way. I thought initially that after having declared my array before the fetch, and pushing the data to it, returning the array at the end of the function would allow me to access the array with all the data in it. What really was happening was that while the fetch request was being made, JavaScript went ahead and executed the code below it, and in short, it was returning the array BEFORE the fetch request was even finished. I was able to remedy this by creating a separate function that took the array as a argument and I called that function after pushing the data to the array.

My solution:

.then((resistances) => {
          for (let types of resistances.damage_relations.half_damage_from) {
            resist.push(types.name);
            updateTableWithResistances(resist, pokemon.id); //<- calling another function INSTEAD of returning the array
            resist.length = 0;
          }
Enter fullscreen mode Exit fullscreen mode

So instead of returning the array itself and doing the thing I wanted with it, I leveraged a function that did the manipulation that I wanted.

Hopefully by now, you understand a lot more about synchronous functions and how they can sometimes be misunderstood , but in the right hands can be a powerful tool. Thank you for reading my blog!

Top comments (0)