loading...
Cover image for Day 4: Exploring async and await in JavaScript
Feldroy

Day 4: Exploring async and await in JavaScript

danielfeldroy profile image Daniel Feldroy ・2 min read

I've always enjoyed the feeling of JavaScript promises, possibly because they feel more explicit than what I've read about await and async. I've also used await and async in Python, and have always wished async code there was implemented with JavaScript-style promises.

However, a lot of JavaScript code is written with await and async, so I decided to knuckle down and get familiar with them.

First I defined a function that returned a promise and would take some time:

function squareXAndWaitXSeconds(x) { 
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x*x); // square the result
    }, x * 1000); // delay by x seconds
  });
}

Then I wrote an async function to call the squareXAndWaitXSeconds function:

async function addItem(y) {
  var x = await squareXAndWaitXSeconds(y); // await for the response
  console.log(x); // Log the response
}

While this worked, it was hard to see it in action. So I used HTML for better display:

<link href="https://unpkg.com/tailwindcss@^1.2/dist/tailwind.min.css" rel="stylesheet">

<div class="container">
  <h1 class="text-4xl">Playing with Await/Async</h1>

  <!-- Use an ordered list to display the results in order they appear -->
  <ol id="result" class="list-decimal px-10">
  </ol>
</div>

I modified the addItem function to post the result in li tags inside the ordered list:

 async function addItem(y) {
  var x = await squareXAndWaitXSeconds(y);

  // Show x  when it's done being awaited
  var li = document.createElement('li');
  li.setAttribute("class", "text-green-600");
  var sentence = `Returning ${x} from ${y} in ${y} seconds`
  var text = document.createTextNode(sentence);
  li.appendChild(text);
  result.appendChild(li);  
}

This was much better, but I wanted a spread of numbers to evaluate. I used a for...of loop to give me better insight into what was happening:

// Count down from 5 so we can see that higher number values
// generate results after lower number values. Nothing blocks!
for (let i of [5,4,3,2,1]){
  // Show we're testing "i" immediately
  var li = document.createElement('li');
  li.setAttribute("class", "text-red-600");
  var text = document.createTextNode(`Testing ${i}`);
  li.appendChild(text);
  result.appendChild(li);

  // run the addItem() function. It won't show until i second(s) pass.
  addItem(i);
}

In My Own Words: What's Happening

The addItem() function is labeled async, meaning that it won't block while it "waits" for the await called function (squareXandWaitXSeconds) to finish evaluating. The logic flow keeps going, hence addItem() is an asynchronous function.

The setTimeout function is used here to test this capability. In other circumstances, this could be used to render complex data on a screen (including games), call an API, or access a database.

You can see where I noodled this out in this codepen:

Posted on Apr 21 by:

danielfeldroy profile

Daniel Feldroy

@danielfeldroy

Engineer and writer. Co-author of Django Crash Course & Two Scoops of Django, Husband of @audreyfeldroy 💘, father of Uma 🍼

Feldroy

The little creative company behind Two Scoops Press, Impossible Hero Books, Fuzzy Rainbow, and an upcoming SaaS product.

Discussion

markdown guide