DEV Community

marthaeochoa
marthaeochoa

Posted on

My Problem with Asynchronous Code

When working on my simple application, one thing I kept forgetting about and continued to struggle with was asynchronous code and the things I could and couldn't do with it.
I struggled to find a reason as to why my buttons were not working the way they should have been. Forget working, the buttons were not even active! It was as if I was trying to call a button that did not exist...
I grew frustrated, and one thing I should have done earlier was ask for help, because once I recevied help, I realized that my problem had such a simple fix; If I had only remembered asynchronous code.

You see, I got so used to synchronous coding and how with that, its so easy. If it's on the page, it exists. With synchronous coding, your code runs line by line, top to bottom.
So for example...

const puppies = "Thor and Hela"
console.log(puppies)
// Thor and Hela
Enter fullscreen mode Exit fullscreen mode

Here we are able to get back the result because the code is synchronous.
But, what I was trying to do was call "puppies" in a place where "puppies" was not real yet.

My real example consisted of using fetches. In my application, I created a GET fetch in order to obtain information from a db.json file. Once I did that, I created HTML elements for the information I received to be rendered on to my application. This included an < h2 >, < div >, two < p >, and a < button >. Like so..

function renderData(data){
let data = document.createElement('li')
data.innerHTML = `
<div id="content">
    <h2>${data.firstValue}</h2>
    <p>Second Value: ${data.secondValue} </p>
    <p>Third Value: ${data.thirdValue}</p>
    </div>
    <div class="button">
    <button>Click!</button>
    </div>
    `
document.querySelector('#data-list').appendChild(data)
}
Enter fullscreen mode Exit fullscreen mode

This alone, worked perfectly! It displayed all the information on my page! Great!! Now all I needed was to get that button to click! So how about adding an event listener? Sounds good, right?

  <button>Click!</button>
    </div>
    `
document.querySelector('#data-list').appendChild(data)
}

const button = document.getElementsByClassName("button")
button.addEventListener("Click", ()=>{
alert('You clicked me!')
}

Enter fullscreen mode Exit fullscreen mode

Great! What could possibly go wrong?

Image description

Okay, in this moment I felt like Javascript made a mistake! In all it's time being a reliable coding language, it made its first mistake with me. Little did I know that the one that made the mistake was actually me, and not the very reliable coding language. I was shocked! It took me a long time and a lot of stress to finally have the courage to ask a cohort
"Can you take a look at my code and see if there's something wrong here?"
Let me tell you, he took one look at my code and immediately said
"Oh, I see what you did"
I was so embarrassed, but he was so helpful and he helped me see the error of my ways. Not by telling me "hey you shouldn't have done this, you should've done this instead" but by saying "How comfortable are you with asynchronous code?" He then walked me through what he meant and helped me debug some things before I came to my own realization of what I had to do. The answer was so simple.

Because I created the button tag as a result of my GET request, the button doesn't technically exist to the rest of my code. The button tag only exists within the renderData function. In order for my event listener to be able to listen for a button, is by having it listen to the button where the button lives.
Turning my code into this:

function renderData(data){
let data = document.createElement('li')
data.innerHTML = `
<div id="content">
    <h2>${data.firstValue}</h2>
    <p>Second Value: ${data.secondValue} </p>
    <p>Third Value: ${data.thirdValue}</p>
    </div>
    <div class="button">
    <button>Click!</button>
    </div>
    `
document.querySelector('#data-list').appendChild(data)

 const button = document.getElementsByClassName("button")
 button.addEventListener("Click", ()=>{
 alert('You clicked me!')
 }
}
Enter fullscreen mode Exit fullscreen mode

Once I moved the event listener to inside the renderData function, I was then able to successfully grab the button and add an event listener to it. If I tried to call that event listener anywhere else, it simply would not be able to grab that button.. no matter how many times you try it out in the console...

The fact that the renderData function was only activated by the GET request promise, is what makes that function asynchrounous. It doesn't run in order in which it is written. It won't run until the GET request is complete. Therefore, the button doesn't exist outside of that function.

This experience helped me understand asynchrounous code a little better, don't get me wrong, it is still a complicated concept. You just need to experience that error in order to open your eyes and see what asynchronous code actually looks like.

Top comments (0)